source: trunk/oscam.c@ 6598

Last change on this file since 6598 was 6598, checked in by corsair, 11 years ago

dvbapi: added auto-lb
emm: fixed emm skipping+logging

File size: 134.5 KB
Line 
1 //FIXME Not checked on threadsafety yet; after checking please remove this line
2#define CS_CORE
3#include "globals.h"
4#include "csctapi/icc_async.h"
5#ifdef MODULE_CCCAM
6#include "module-cccam.h"
7#endif
8#if defined(AZBOX) && defined(HAVE_DVBAPI)
9#include "openxcas/openxcas_api.h"
10#endif
11#define CS_VERSION_X CS_VERSION
12#ifdef COOL
13void coolapi_close_all();
14void coolapi_open_all();
15#endif
16
17static void cs_fake_client(struct s_client *client, char *usr, int32_t uniq, in_addr_t ip);
18static void chk_dcw(struct s_client *cl, struct s_ecm_answer *ea);
19
20/*****************************************************************************
21 Globals
22*****************************************************************************/
23int32_t exit_oscam=0;
24struct s_module ph[CS_MAX_MOD]; // Protocols
25struct s_cardsystem cardsystem[CS_MAX_MOD];
26struct s_cardreader cardreader[CS_MAX_MOD];
27
28struct s_client * first_client = NULL; //Pointer to clients list, first client is master
29struct s_reader * first_active_reader = NULL; //list of active readers (enable=1 deleted = 0)
30LLIST * configured_readers = NULL; //list of all (configured) readers
31
32uint16_t len4caid[256]; // table for guessing caid (by len)
33char cs_confdir[128]=CS_CONFDIR;
34uint16_t cs_dblevel=0; // Debug Level
35int32_t thread_pipe[2] = {0, 0};
36#ifdef WEBIF
37int8_t cs_restart_mode=1; //Restartmode: 0=off, no restart fork, 1=(default)restart fork, restart by webif, 2=like=1, but also restart on segfaults
38uint8_t cs_http_use_utf8 = 0;
39#endif
40int8_t cs_capture_SEGV=0;
41int8_t cs_dump_stack=0;
42uint16_t cs_waittime = 60;
43char cs_tmpdir[200]={0x00};
44pid_t server_pid=0;
45#if defined(LIBUSB)
46CS_MUTEX_LOCK sr_lock;
47#endif
48#ifdef ARM
49pthread_t arm_led_thread = 0;
50LLIST *arm_led_actions = NULL;
51#endif
52CS_MUTEX_LOCK system_lock;
53CS_MUTEX_LOCK gethostbyname_lock;
54CS_MUTEX_LOCK clientlist_lock;
55CS_MUTEX_LOCK readerlist_lock;
56CS_MUTEX_LOCK fakeuser_lock;
57CS_MUTEX_LOCK ecmcache_lock;
58CS_MUTEX_LOCK readdir_lock;
59pthread_key_t getclient;
60
61struct s_client *timecheck_client;
62
63//Cache for ecms, cws and rcs:
64struct ecm_request_t *ecmcwcache = NULL;
65uint32_t ecmcwcache_size = 0;
66
67struct s_config cfg;
68
69char *prog_name = NULL;
70char *processUsername = NULL;
71#if defined(WEBIF) || defined(MODULE_MONITOR)
72char *loghist = NULL; // ptr of log-history
73char *loghistptr = NULL;
74#endif
75
76#ifdef CS_CACHEEX
77int32_t cs_add_cacheex_stats(struct s_client *cl, uint16_t caid, uint16_t srvid, uint32_t prid, uint8_t direction) {
78
79 if (!cfg.cacheex_enable_stats)
80 return -1;
81
82 // create list if doesn't exist
83 if (!cl->ll_cacheex_stats)
84 cl->ll_cacheex_stats = ll_create("ll_cacheex_stats");
85
86 time_t now = time((time_t*)0);
87 LL_ITER itr = ll_iter_create(cl->ll_cacheex_stats);
88 S_CACHEEX_STAT_ENTRY *cacheex_stats_entry;
89
90 // check for existing entry
91 while ((cacheex_stats_entry = ll_iter_next(&itr))) {
92 if (cacheex_stats_entry->cache_srvid == srvid &&
93 cacheex_stats_entry->cache_caid == caid &&
94 cacheex_stats_entry->cache_prid == prid &&
95 cacheex_stats_entry->cache_direction == direction) {
96 // we already have this entry - just add count and time
97 cacheex_stats_entry->cache_count++;
98 cacheex_stats_entry->cache_last = now;
99 return cacheex_stats_entry->cache_count;
100 }
101 }
102
103 // if we land here we have to add a new entry
104 if(cs_malloc(&cacheex_stats_entry, sizeof(S_CACHEEX_STAT_ENTRY), -1)){
105 cacheex_stats_entry->cache_caid = caid;
106 cacheex_stats_entry->cache_srvid = srvid;
107 cacheex_stats_entry->cache_prid = prid;
108 cacheex_stats_entry->cache_count = 1;
109 cacheex_stats_entry->cache_last = now;
110 cacheex_stats_entry->cache_direction = direction;
111 ll_iter_insert(&itr, cacheex_stats_entry);
112 return 1;
113 }
114 return 0;
115}
116#endif
117
118int32_t cs_check_v(uint32_t ip, int32_t port, int32_t add, char *info) {
119 int32_t result = 0;
120 if (cfg.failbantime) {
121
122 if (!cfg.v_list)
123 cfg.v_list = ll_create("v_list");
124
125 time_t now = time((time_t*)0);
126 LL_ITER itr = ll_iter_create(cfg.v_list);
127 V_BAN *v_ban_entry;
128 int32_t ftime = cfg.failbantime*60;
129
130 //run over all banned entries to do housekeeping:
131 while ((v_ban_entry=ll_iter_next(&itr))) {
132
133 // housekeeping:
134 if ((now - v_ban_entry->v_time) >= ftime) { // entry out of time->remove
135 free(v_ban_entry->info);
136 ll_iter_remove_data(&itr);
137 continue;
138 }
139
140 if (ip == v_ban_entry->v_ip && port == v_ban_entry->v_port ) {
141 result=1;
142 if (!info) info = v_ban_entry->info;
143 else if (!v_ban_entry->info) {
144 int32_t size = strlen(info)+1;
145 v_ban_entry->info = cs_malloc(&v_ban_entry->info, size, -1);
146 strncpy(v_ban_entry->info, info, size);
147 }
148
149 if (!add) {
150 if (v_ban_entry->v_count >= cfg.failbancount) {
151 cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - %ld seconds left%s%s",
152 cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port,
153 ftime - (now - v_ban_entry->v_time), info?", info: ":"", info?info:"");
154 } else {
155 cs_debug_mask(D_TRACE, "failban: ip %s:%d chance %d of %d%s%s",
156 cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port,
157 v_ban_entry->v_count, cfg.failbancount, info?", info: ":"", info?info:"");
158
159 v_ban_entry->v_count++;
160 }
161 }
162 else {
163 cs_debug_mask(D_TRACE, "failban: banned ip %s:%d - already exist in list%s%s",
164 cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, info?", info: ":"", info?info:"");
165 }
166 }
167 }
168 if (add && !result) {
169 if(cs_malloc(&v_ban_entry, sizeof(V_BAN), -1)){
170 v_ban_entry->v_time = time((time_t *)0);
171 v_ban_entry->v_ip = ip;
172 v_ban_entry->v_port = port;
173 v_ban_entry->v_count = 1;
174 if (info) {
175 int32_t size = strlen(info)+1;
176 v_ban_entry->info = cs_malloc(&v_ban_entry->info, size, -1);
177 strncpy(v_ban_entry->info, info, size);
178 }
179
180 ll_iter_insert(&itr, v_ban_entry);
181
182 cs_debug_mask(D_TRACE, "failban: ban ip %s:%d with timestamp %ld%s%s",
183 cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port, v_ban_entry->v_time,
184 info?", info: ":"", info?info:"");
185 }
186 }
187 }
188 return result;
189}
190
191int32_t cs_check_violation(uint32_t ip, int32_t port) {
192 return cs_check_v(ip, port, 0, NULL);
193}
194void cs_add_violation_by_ip(uint32_t ip, int32_t port, char *info) {
195 cs_check_v(ip, port, 1, info);
196}
197
198void cs_add_violation(struct s_client *cl, char *info) {
199 cs_add_violation_by_ip((uint32_t)cl->ip, ph[cl->ctyp].ptab ? ph[cl->ctyp].ptab->ports[cl->port_idx].s_port : 0, info);
200}
201
202#ifdef WEBIF
203void cs_add_lastresponsetime(struct s_client *cl, int32_t ltime, time_t timestamp, int32_t rc){
204
205 if(cl->cwlastresptimes_last == CS_ECM_RINGBUFFER_MAX - 1){
206 cl->cwlastresptimes_last = 0;
207 } else {
208 cl->cwlastresptimes_last++;
209 }
210 cl->cwlastresptimes[cl->cwlastresptimes_last].duration = ltime > 9999 ? 9999 : ltime;
211 cl->cwlastresptimes[cl->cwlastresptimes_last].timestamp = timestamp;
212 cl->cwlastresptimes[cl->cwlastresptimes_last].rc = rc;
213}
214#endif
215
216/*****************************************************************************
217 Statics
218*****************************************************************************/
219static const char *logo = " ___ ____ ___ \n / _ \\/ ___| / __|__ _ _ __ ___ \n| | | \\___ \\| | / _` | '_ ` _ \\ \n| |_| |___) | |_| (_| | | | | | |\n \\___/|____/ \\___\\__,_|_| |_| |_|\n";
220
221/* Prints usage information and information about the built-in modules. */
222static void usage()
223{
224 fprintf(stderr, "%s\n\n", logo);
225 fprintf(stderr, "OSCam cardserver v%s, build #%s (%s) - (w) 2009-2012 Streamboard SVN\n", CS_VERSION_X, CS_SVN_VERSION, CS_OSTYPE);
226 fprintf(stderr, "\tsee http://streamboard.gmc.to/oscam/ for more details\n");
227 fprintf(stderr, "\tbased on Streamboard mp-cardserver v0.9d - (w) 2004-2007 by dukat\n");
228 fprintf(stderr, "\tThis program is distributed under GPL.\n");
229 fprintf(stderr, "\tinbuilt add-ons: ");
230#ifdef WEBIF
231 fprintf(stderr, "webif ");
232#endif
233#ifdef MODULE_MONITOR
234 fprintf(stderr, "monitor ");
235#endif
236#ifdef WITH_SSL
237 fprintf(stderr, "ssl ");
238#endif
239#ifdef HAVE_DVBAPI
240#ifdef WITH_STAPI
241 fprintf(stderr, "dvbapi_stapi ");
242#else
243 fprintf(stderr, "dvbapi ");
244#endif
245#endif
246#ifdef IRDETO_GUESSING
247 fprintf(stderr, "irdeto-guessing ");
248#endif
249#ifdef CS_ANTICASC
250 fprintf(stderr, "anticascading ");
251#endif
252#ifdef WITH_DEBUG
253 fprintf(stderr, "debug ");
254#endif
255#ifdef LIBUSB
256 fprintf(stderr, "smartreader ");
257#endif
258#ifdef HAVE_PCSC
259 fprintf(stderr, "pcsc ");
260#endif
261#ifdef WITH_LB
262 fprintf(stderr, "loadbalancing ");
263#endif
264#ifdef LCDSUPPORT
265 fprintf(stderr, "lcd ");
266#endif
267 fprintf(stderr, "\n\tinbuilt protocols: ");
268#ifdef MODULE_CAMD33
269 fprintf(stderr, "camd33 ");
270#endif
271#ifdef MODULE_CAMD35
272 fprintf(stderr, "camd35_udp ");
273#endif
274#ifdef MODULE_CAMD35_TCP
275 fprintf(stderr, "camd35_tcp ");
276#endif
277#ifdef MODULE_NEWCAMD
278 fprintf(stderr, "newcamd ");
279#endif
280#ifdef MODULE_CCCAM
281 fprintf(stderr, "cccam ");
282#endif
283#ifdef MODULE_CCCSHARE
284 fprintf(stderr, "cccam share ");
285#endif
286#ifdef MODULE_PANDORA
287 fprintf(stderr, "pandora ");
288#endif
289#ifdef CS_CACHEEX
290 fprintf(stderr, "cache-exchange ");
291#endif
292#ifdef MODULE_GBOX
293 fprintf(stderr, "gbox ");
294#endif
295#ifdef MODULE_RADEGAST
296 fprintf(stderr, "radegast ");
297#endif
298#ifdef MODULE_SERIAL
299 fprintf(stderr, "serial ");
300#endif
301#ifdef MODULE_CONSTCW
302 fprintf(stderr, "constcw ");
303#endif
304 fprintf(stderr, "\n\tinbuilt cardreaders: ");
305#ifdef READER_NAGRA
306 fprintf(stderr, "nagra ");
307#endif
308#ifdef READER_IRDETO
309 fprintf(stderr, "irdeto ");
310#endif
311#ifdef READER_CONAX
312 fprintf(stderr, "conax ");
313#endif
314#ifdef READER_CRYPTOWORKS
315 fprintf(stderr, "cryptoworks ");
316#endif
317#ifdef READER_SECA
318 fprintf(stderr, "seca ");
319#endif
320#ifdef READER_VIACCESS
321 fprintf(stderr, "viaccess ");
322#endif
323#ifdef READER_VIDEOGUARD
324 fprintf(stderr, "videoguard ");
325#endif
326#ifdef READER_DRE
327 fprintf(stderr, "dre ");
328#endif
329#ifdef READER_TONGFANG
330 fprintf(stderr, "tongfang ");
331#endif
332 fprintf(stderr, "\n\n");
333#ifdef WEBIF
334 fprintf(stderr, "oscam [-a] [-b] [-s] [-c <config dir>] [-t <tmp dir>] [-d <level>] [-r <level>] [-w <secs>] [-g <mode>] [-u] [-h]");
335#else
336 fprintf(stderr, "oscam [-a] [-b] [-s] [-c <config dir>] [-t <tmp dir>] [-d <level>] [-w <secs>] [-g <mode>] [-h]");
337#endif
338 fprintf(stderr, "\n\n\t-a : write oscam.crash on segfault (needs installed GDB and OSCam compiled with debug infos -ggdb)\n");
339 fprintf(stderr, "\t-b : start in background\n");
340 fprintf(stderr, "\t-s : capture segmentation faults\n");
341 fprintf(stderr, "\t-c <dir> : read configuration from <dir>\n");
342 fprintf(stderr, "\t default = %s\n", CS_CONFDIR);
343 fprintf(stderr, "\t-t <dir> : tmp dir <dir>\n");
344#ifdef CS_CYGWIN32
345 fprintf(stderr, "\t default = (OS-TMP)\n");
346#else
347 fprintf(stderr, "\t default = /tmp/.oscam\n");
348#endif
349 fprintf(stderr, "\t-d <level> : debug level mask\n");
350 fprintf(stderr, "\t 0 = no debugging (default)\n");
351 fprintf(stderr, "\t 1 = detailed error messages\n");
352 fprintf(stderr, "\t 2 = ATR parsing info, ECM, EMM and CW dumps\n");
353 fprintf(stderr, "\t 4 = traffic from/to the reader\n");
354 fprintf(stderr, "\t 8 = traffic from/to the clients\n");
355 fprintf(stderr, "\t 16 = traffic to the reader-device on IFD layer\n");
356 fprintf(stderr, "\t 32 = traffic to the reader-device on I/O layer\n");
357 fprintf(stderr, "\t 64 = EMM logging\n");
358 fprintf(stderr, "\t 128 = DVBAPI logging\n");
359 fprintf(stderr, "\t 255 = debug all\n");
360#ifdef WEBIF
361 fprintf(stderr, "\t-r <level> : restart level\n");
362 fprintf(stderr, "\t 0 = disabled, restart request sets exit status 99\n");
363 fprintf(stderr, "\t 1 = restart activated, web interface can restart oscam (default)\n");
364 fprintf(stderr, "\t 2 = like 1, but also restart on segmentation faults\n");
365#endif
366 fprintf(stderr, "\t-g <mode> : garbage collector debug mode (1=immediate free, 2=check for double frees); these options are only intended for debug!\n");
367 fprintf(stderr, "\t-w <secs> : wait up to <secs> seconds for the system time to be set correctly (default 60)\n");
368#ifdef WEBIF
369 fprintf(stderr, "\t-u : enable output of web interface in UTF-8 charset\n");
370#endif
371 fprintf(stderr, "\t-h : show this help\n");
372 fprintf(stderr, "\n");
373 exit(1);
374}
375
376#ifdef NEED_DAEMON
377#ifdef OS_MACOSX
378// this is done because daemon is being deprecated starting with 10.5 and -Werror will always trigger an error
379static int32_t daemon_compat(int32_t nochdir, int32_t noclose)
380#else
381static int32_t daemon(int32_t nochdir, int32_t noclose)
382#endif
383{
384 int32_t fd;
385
386 switch (fork())
387 {
388 case -1: return (-1);
389 case 0: break;
390 default: _exit(0);
391 }
392
393 if (setsid()==(-1))
394 return(-1);
395
396 if (!nochdir)
397 (void)chdir("/");
398
399 if (!noclose && (fd=open("/dev/null", O_RDWR, 0)) != -1)
400 {
401 (void)dup2(fd, STDIN_FILENO);
402 (void)dup2(fd, STDOUT_FILENO);
403 (void)dup2(fd, STDERR_FILENO);
404 if (fd>2)
405 (void)close(fd);
406 }
407 return(0);
408}
409#endif
410
411int32_t recv_from_udpipe(uchar *buf)
412{
413 uint16_t n;
414 if (buf[0]!='U')
415 {
416 cs_log("INTERNAL PIPE-ERROR");
417 cs_exit(1);
418 }
419 memcpy(&n, buf+1, 2);
420
421 memmove(buf, buf+3, n);
422
423 return n;
424}
425
426/* Returns the username from the client. You will always get a char reference back (no NULLs but it may be string containting "NULL")
427 which you should never modify and not free()! */
428char *username(struct s_client * client)
429{
430 if (!client)
431 return "NULL";
432
433 if (client->typ == 's' || client->typ == 'h' || client->typ == 'a')
434 {
435 return processUsername?processUsername:"NULL";
436 }
437
438 if (client->typ == 'c' || client->typ == 'm') {
439 struct s_auth *acc = client->account;
440 if(acc)
441 {
442 if (acc->usr[0])
443 return acc->usr;
444 else
445 return "anonymous";
446 }
447 else
448 {
449 return "NULL";
450 }
451 } else if (client->typ == 'r' || client->typ == 'p'){
452 struct s_reader *rdr = client->reader;
453 if(rdr)
454 return rdr->label;
455 }
456 return "NULL";
457}
458
459static struct s_client * idx_from_ip(in_addr_t ip, in_port_t port)
460{
461 struct s_client *cl;
462 for (cl=first_client; cl ; cl=cl->next)
463 if (!cl->kill && (cl->ip==ip) && (cl->port==port) && ((cl->typ=='c') || (cl->typ=='m')))
464 return cl;
465 return NULL;
466}
467
468static int32_t chk_caid(uint16_t caid, CAIDTAB *ctab)
469{
470 int32_t n;
471 int32_t rc;
472 for (rc=(-1), n=0; (n<CS_MAXCAIDTAB) && (rc<0); n++)
473 if ((caid & ctab->mask[n]) == ctab->caid[n])
474 rc=ctab->cmap[n] ? ctab->cmap[n] : caid;
475 return(rc);
476}
477
478int32_t chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab)
479{
480 int32_t caid;
481 if ((caid=chk_caid(er->caid, ctab))<0)
482 return(0);
483 er->caid=caid;
484 return(1);
485}
486
487#ifdef WEBIF
488void clear_account_stats(struct s_auth *account)
489{
490 account->cwfound = 0;
491 account->cwcache = 0;
492 account->cwnot = 0;
493 account->cwtun = 0;
494 account->cwignored = 0;
495 account->cwtout = 0;
496 account->emmok = 0;
497 account->emmnok = 0;
498#ifdef CS_CACHEEX
499 account->cwcacheexgot = 0;
500 account->cwcacheexpush = 0;
501 account->cwcacheexhit = 0;
502#endif
503}
504
505void clear_all_account_stats()
506{
507 struct s_auth *account = cfg.account;
508 while (account) {
509 clear_account_stats(account);
510 account = account->next;
511 }
512}
513
514void clear_system_stats()
515{
516 first_client->cwfound = 0;
517 first_client->cwcache = 0;
518 first_client->cwnot = 0;
519 first_client->cwtun = 0;
520 first_client->cwignored = 0;
521 first_client->cwtout = 0;
522 first_client->emmok = 0;
523 first_client->emmnok = 0;
524#ifdef CS_CACHEEX
525 first_client->cwcacheexgot = 0;
526 first_client->cwcacheexpush = 0;
527 first_client->cwcacheexhit = 0;
528#endif
529}
530#endif
531
532void cs_accounts_chk()
533{
534 struct s_auth *old_accounts = cfg.account;
535 struct s_auth *new_accounts = init_userdb();
536 struct s_auth *account1,*account2;
537 for (account1=cfg.account; account1; account1=account1->next) {
538 for (account2=new_accounts; account2; account2=account2->next) {
539 if (!strcmp(account1->usr, account2->usr)) {
540 account2->cwfound = account1->cwfound;
541 account2->cwcache = account1->cwcache;
542 account2->cwnot = account1->cwnot;
543 account2->cwtun = account1->cwtun;
544 account2->cwignored = account1->cwignored;
545 account2->cwtout = account1->cwtout;
546 account2->emmok = account1->emmok;
547 account2->emmnok = account1->emmnok;
548 account2->firstlogin = account1->firstlogin;
549#ifdef CS_ANTICASC
550 account2->ac_users = account1->ac_users;
551 account2->ac_penalty = account1->ac_penalty;
552 account2->ac_stat = account1->ac_stat;
553#endif
554 }
555 }
556 }
557 cs_reinit_clients(new_accounts);
558 cfg.account = new_accounts;
559 init_free_userdb(old_accounts);
560
561#ifdef CS_ANTICASC
562 ac_clear();
563#endif
564}
565
566static void free_ecm(ECM_REQUEST *ecm) {
567 struct s_ecm_answer *ea, *nxt;
568
569 ea = ecm->matching_rdr;
570 ecm->matching_rdr = NULL;
571 while (ea) {
572 nxt = ea->next;
573 add_garbage(ea);
574 ea = nxt;
575 }
576#ifdef CS_CACHEEX
577 ll_destroy_data(ecm->csp_lastnodes);
578 ecm->csp_lastnodes = NULL;
579#endif
580 add_garbage(ecm);
581}
582
583
584static void cleanup_ecmtasks(struct s_client *cl)
585{
586 ECM_REQUEST *ecm;
587 struct s_ecm_answer *ea_list, *ea_prev;
588
589 if (cl->ecmtask) {
590 int32_t i;
591 for (i=0; i<CS_MAXPENDING; i++) {
592 ecm = &cl->ecmtask[i];
593 ecm->matching_rdr=NULL;
594 ecm->client = NULL;
595 }
596 add_garbage(cl->ecmtask);
597 cl->ecmtask = NULL;
598 }
599
600 if (cl->cascadeusers) {
601 ll_destroy_data(cl->cascadeusers);
602 cl->cascadeusers = NULL;
603 }
604
605 //remove this clients ecm from queue. because of cache, just null the client:
606 cs_readlock(&ecmcache_lock);
607 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
608 if (ecm->client == cl)
609 ecm->client = NULL;
610#ifdef CS_CACHEEX
611 if (ecm->cacheex_src == cl)
612 ecm->cacheex_src = NULL;
613#endif
614 //cl is a reader, remove from matching_rdr:
615 for(ea_list = ecm->matching_rdr, ea_prev=NULL; ea_list; ea_prev = ea_list, ea_list = ea_list->next) {
616 if (ea_list->reader->client == cl) {
617 if (ea_prev)
618 ea_prev->next = ea_list->next;
619 else
620 ecm->matching_rdr = ea_list->next;
621 add_garbage(ea_list);
622 }
623 }
624
625 }
626 cs_readunlock(&ecmcache_lock);
627
628 //remove client from rdr ecm-queue:
629 cs_readlock(&readerlist_lock);
630 struct s_reader *rdr = first_active_reader;
631 while (rdr) {
632 if (rdr->client && rdr->client->ecmtask) {
633 ECM_REQUEST *ecm;
634 int i;
635 for (i=0; i<CS_MAXPENDING; i++) {
636 ecm = &rdr->client->ecmtask[i];
637 if (ecm->client == cl)
638 ecm->client = NULL;
639 }
640 }
641 rdr=rdr->next;
642 }
643 cs_readunlock(&readerlist_lock);
644}
645
646void cleanup_thread(void *var)
647{
648 struct s_client *cl = var;
649 if(!cl) return;
650 struct s_reader *rdr = cl->reader;
651
652 // Remove client from client list. kill_thread also removes this client, so here just if client exits itself...
653 struct s_client *prev, *cl2;
654 cs_writelock(&clientlist_lock);
655 cl->kill = 1;
656 for (prev=first_client, cl2=first_client->next; prev->next != NULL; prev=prev->next, cl2=cl2->next)
657 if (cl == cl2)
658 break;
659 if (cl == cl2)
660 prev->next = cl2->next; //remove client from list
661 cs_writeunlock(&clientlist_lock);
662
663 // Clean reader. The cleaned structures should be only used by the reader thread, so we should be save without waiting
664 if (rdr){
665 remove_reader_from_active(rdr);
666 if(rdr->ph.cleanup)
667 rdr->ph.cleanup(cl);
668#ifdef WITH_CARDREADER
669 if (cl->typ == 'r')
670 ICC_Async_Close(rdr);
671#endif
672 if (cl->typ == 'p')
673 network_tcp_connection_close(rdr, "cleanup");
674 cl->reader = NULL;
675 }
676
677 // Clean client specific data
678 if(cl->typ == 'c'){
679 cs_statistics(cl);
680 cl->last_caid = 0xFFFF;
681 cl->last_srvid = 0xFFFF;
682 cs_statistics(cl);
683
684 cs_sleepms(500); //just wait a bit that really really nobody is accessing client data
685
686 if(ph[cl->ctyp].cleanup)
687 ph[cl->ctyp].cleanup(cl);
688 }
689
690 // Close network socket if not already cleaned by previous cleanup functions
691 if(cl->pfd)
692 close(cl->pfd);
693
694 // Clean all remaining structures
695
696 pthread_mutex_trylock(&cl->thread_lock);
697 ll_destroy_data(cl->joblist);
698 cl->joblist = NULL;
699 cl->account = NULL;
700 pthread_mutex_unlock(&cl->thread_lock);
701 pthread_mutex_destroy(&cl->thread_lock);
702
703 cleanup_ecmtasks(cl);
704 add_garbage(cl->emmcache);
705#ifdef MODULE_CCCAM
706 add_garbage(cl->cc);
707#endif
708#ifdef MODULE_SERIAL
709 add_garbage(cl->serialdata);
710#endif
711 add_garbage(cl);
712}
713
714static void cs_cleanup()
715{
716#ifdef WITH_LB
717 if (cfg.lb_mode && cfg.lb_save) {
718 save_stat_to_file(0);
719 cfg.lb_save = 0; //this is for avoiding duplicate saves
720 }
721#endif
722
723#ifdef MODULE_CCCAM
724#ifdef MODULE_CCCSHARE
725 done_share();
726#endif
727#endif
728
729 //cleanup clients:
730 struct s_client *cl;
731 for (cl=first_client->next; cl; cl=cl->next) {
732 if (cl->typ=='c'){
733 if(cl->account && cl->account->usr)
734 cs_log("killing client %s", cl->account->usr);
735 kill_thread(cl);
736 }
737 }
738
739 //cleanup readers:
740 struct s_reader *rdr;
741 for (rdr=first_active_reader; rdr ; rdr=rdr->next) {
742 cl = rdr->client;
743 if(cl){
744 cs_log("killing reader %s", rdr->label);
745 kill_thread(cl);
746 // Stop MCR reader display thread
747 if (cl->typ == 'r' && cl->reader && cl->reader->typ == R_SC8in1
748 && cl->reader->sc8in1_config && cl->reader->sc8in1_config->display_running) {
749 cl->reader->sc8in1_config->display_running = FALSE;
750 }
751 }
752 }
753 first_active_reader = NULL;
754
755 init_free_userdb(cfg.account);
756 cfg.account = NULL;
757 init_free_sidtab();
758}
759
760/*
761 * flags: 1 = restart, 2 = don't modify if SIG_IGN, may be combined
762 */
763void set_signal_handler(int32_t sig, int32_t flags, void (*sighandler))
764{
765#ifdef CS_SIGBSD
766 if ((signal(sig, sighandler)==SIG_IGN) && (flags & 2))
767 {
768 signal(sig, SIG_IGN);
769 siginterrupt(sig, 0);
770 }
771 else
772 siginterrupt(sig, (flags & 1) ? 0 : 1);
773#else
774 struct sigaction sa;
775 sigaction(sig, (struct sigaction *) 0, &sa);
776 if (!((flags & 2) && (sa.sa_handler==SIG_IGN)))
777 {
778 sigemptyset(&sa.sa_mask);
779 sa.sa_flags=(flags & 1) ? SA_RESTART : 0;
780 sa.sa_handler=sighandler;
781 sigaction(sig, &sa, (struct sigaction *) 0);
782 }
783#endif
784}
785
786static void cs_master_alarm()
787{
788 cs_log("PANIC: master deadlock!");
789 fprintf(stderr, "PANIC: master deadlock!");
790 fflush(stderr);
791}
792
793static void cs_sigpipe()
794{
795 if (cs_dblevel & D_ALL_DUMP)
796 cs_log("Got sigpipe signal -> captured");
797}
798
799static void cs_dummy() {
800 return;
801}
802
803/* Switch debuglevel forward one step (called when receiving SIGUSR1). */
804void cs_debug_level(){
805 switch (cs_dblevel) {
806 case 0:
807 cs_dblevel = 1;
808 break;
809 case 128:
810 cs_dblevel = 255;
811 break;
812 case 255:
813 cs_dblevel = 0;
814 break;
815 default:
816 cs_dblevel <<= 1;
817 }
818
819 cs_log("debug_level=%d", cs_dblevel);
820}
821
822void cs_card_info()
823{
824 struct s_client *cl;
825 for (cl=first_client->next; cl ; cl=cl->next)
826 if( cl->typ=='r' && cl->reader )
827 add_job(cl, ACTION_READER_CARDINFO, NULL, 0);
828}
829
830/**
831 * write stacktrace to oscam.crash. file is always appended
832 * Usage:
833 * 1. compile oscam with debug parameters (Makefile: DS_OPTS="-ggdb")
834 * 2. you need gdb installed and working on the local machine
835 * 3. start oscam with parameter: -a
836 */
837void cs_dumpstack(int32_t sig)
838{
839 FILE *fp = fopen("oscam.crash", "a+");
840
841 time_t timep;
842 char buf[200];
843
844 time(&timep);
845 cs_ctime_r(&timep, buf);
846
847 fprintf(stderr, "oscam crashed with signal %d on %swriting oscam.crash\n", sig, buf);
848
849 fprintf(fp, "%sFATAL: Signal %d: %s Fault. Logged StackTrace:\n\n", buf, sig, (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
850 fclose(fp);
851
852 FILE *cmd = fopen("/tmp/gdbcmd", "w");
853 fputs("bt\n", cmd);
854 fputs("thread apply all bt\n", cmd);
855 fclose(cmd);
856
857 snprintf(buf, sizeof(buf)-1, "gdb %s %d -batch -x /tmp/gdbcmd >> oscam.crash", prog_name, getpid());
858 if(system(buf) == -1)
859 fprintf(stderr, "Fatal error on trying to start gdb process.");
860
861 exit(-1);
862}
863
864
865/**
866 * called by signal SIGHUP
867 *
868 * reloads configs:
869 * - useraccounts (oscam.user)
870 * - services ids (oscam.srvid)
871 * - tier ids (oscam.tiers)
872 * Also clears anticascading stats.
873 **/
874void cs_reload_config()
875{
876 cs_accounts_chk();
877 init_srvid();
878 init_tierid();
879 #ifdef CS_ANTICASC
880 ac_init_stat();
881 #endif
882}
883
884/* Sets signal handlers to ignore for early startup of OSCam because for example log
885 could cause SIGPIPE errors and the normal signal handlers can't be used at this point. */
886static void init_signal_pre()
887{
888 set_signal_handler(SIGPIPE , 1, SIG_IGN);
889 set_signal_handler(SIGWINCH, 1, SIG_IGN);
890 set_signal_handler(SIGALRM , 1, SIG_IGN);
891 set_signal_handler(SIGHUP , 1, SIG_IGN);
892}
893
894/* Sets the signal handlers.*/
895static void init_signal()
896{
897 set_signal_handler(SIGINT, 3, cs_exit);
898 //set_signal_handler(SIGKILL, 3, cs_exit);
899#ifdef OS_MACOSX
900 set_signal_handler(SIGEMT, 3, cs_exit);
901#else
902 //set_signal_handler(SIGPOLL, 3, cs_exit);
903#endif
904 //set_signal_handler(SIGPROF, 3, cs_exit);
905 set_signal_handler(SIGTERM, 3, cs_exit);
906 //set_signal_handler(SIGVTALRM, 3, cs_exit);
907
908 set_signal_handler(SIGWINCH, 1, SIG_IGN);
909 // set_signal_handler(SIGPIPE , 0, SIG_IGN);
910 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
911 // set_signal_handler(SIGALRM , 0, cs_alarm);
912 set_signal_handler(SIGALRM , 0, cs_master_alarm);
913 // set_signal_handler(SIGCHLD , 1, cs_child_chk);
914 set_signal_handler(SIGHUP , 1, cs_reload_config);
915 //set_signal_handler(SIGHUP , 1, cs_sighup);
916 set_signal_handler(SIGUSR1, 1, cs_debug_level);
917 set_signal_handler(SIGUSR2, 1, cs_card_info);
918 set_signal_handler(OSCAM_SIGNAL_WAKEUP, 0, cs_dummy);
919
920 if (cs_capture_SEGV) {
921 set_signal_handler(SIGSEGV, 1, cs_exit);
922 set_signal_handler(SIGBUS, 1, cs_exit);
923 }
924 else if (cs_dump_stack) {
925 set_signal_handler(SIGSEGV, 1, cs_dumpstack);
926 set_signal_handler(SIGBUS, 1, cs_dumpstack);
927 }
928
929
930 cs_log("signal handling initialized (type=%s)",
931#ifdef CS_SIGBSD
932 "bsd"
933#else
934 "sysv"
935#endif
936 );
937 return;
938}
939
940void cs_exit(int32_t sig)
941{
942 if (cs_dump_stack && (sig == SIGSEGV || sig == SIGBUS))
943 cs_dumpstack(sig);
944
945 set_signal_handler(SIGCHLD, 1, SIG_IGN);
946 set_signal_handler(SIGHUP , 1, SIG_IGN);
947 set_signal_handler(SIGPIPE, 1, SIG_IGN);
948
949 if (sig==SIGALRM) {
950 cs_debug_mask(D_TRACE, "thread %8lX: SIGALRM, skipping", (unsigned long)pthread_self());
951 return;
952 }
953
954 if (sig && (sig!=SIGQUIT))
955 cs_log("thread %8lX exit with signal %d", (unsigned long)pthread_self(), sig);
956
957 struct s_client *cl = cur_client();
958 if (!cl)
959 return;
960
961 if(cl->typ == 'h' || cl->typ == 's'){
962#ifdef ARM
963 if(cfg.enableled == 1){
964 cs_switch_led(LED1B, LED_OFF);
965 cs_switch_led(LED2, LED_OFF);
966 cs_switch_led(LED3, LED_OFF);
967 cs_switch_led(LED1A, LED_ON);
968 }
969 arm_led_stop_thread();
970#endif
971#ifdef QBOXHD
972 if(cfg.enableled == 2){
973 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_FAST);
974 qboxhd_led_blink(QBOXHD_LED_COLOR_RED,QBOXHD_LED_BLINK_FAST);
975 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_FAST);
976 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE,QBOXHD_LED_BLINK_FAST);
977 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_FAST);
978 }
979#endif
980#ifdef LCDSUPPORT
981 end_lcd_thread();
982#endif
983
984#ifndef OS_CYGWIN32
985 char targetfile[256];
986 snprintf(targetfile, 255, "%s%s", get_tmp_dir(), "/oscam.version");
987 if (unlink(targetfile) < 0)
988 cs_log("cannot remove oscam version file %s (errno=%d %s)", targetfile, errno, strerror(errno));
989#endif
990#ifdef COOL
991 coolapi_close_all();
992#endif
993 }
994
995 // this is very important - do not remove
996 if (cl->typ != 's') {
997 cs_log("thread %8lX ended!", (unsigned long)pthread_self());
998
999 cleanup_thread(cl);
1000
1001 //Restore signals before exiting thread
1002 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
1003 set_signal_handler(SIGHUP , 1, cs_reload_config);
1004
1005 pthread_exit(NULL);
1006 return;
1007 }
1008
1009 cs_log("cardserver down");
1010 cs_close_log();
1011
1012 if (sig == SIGINT)
1013 exit(sig);
1014
1015 cs_cleanup();
1016
1017 if (!exit_oscam)
1018 exit_oscam = sig?sig:1;
1019}
1020
1021void cs_reinit_clients(struct s_auth *new_accounts)
1022{
1023 struct s_auth *account;
1024 unsigned char md5tmp[MD5_DIGEST_LENGTH];
1025
1026 struct s_client *cl;
1027 for (cl=first_client->next; cl ; cl=cl->next)
1028 if( (cl->typ == 'c' || cl->typ == 'm') && cl->account ) {
1029 for (account = new_accounts; (account) ; account = account->next)
1030 if (!strcmp(cl->account->usr, account->usr))
1031 break;
1032
1033 if (account && !account->disabled && cl->pcrc == crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), md5tmp), MD5_DIGEST_LENGTH)) {
1034 cl->account = account;
1035 if(cl->typ == 'c'){
1036 cl->grp = account->grp;
1037 cl->aureader_list = account->aureader_list;
1038 cl->autoau = account->autoau;
1039 cl->expirationdate = account->expirationdate;
1040 cl->allowedtimeframe[0] = account->allowedtimeframe[0];
1041 cl->allowedtimeframe[1] = account->allowedtimeframe[1];
1042 cl->ncd_keepalive = account->ncd_keepalive;
1043 cl->c35_suppresscmd08 = account->c35_suppresscmd08;
1044 cl->tosleep = (60*account->tosleep);
1045 cl->c35_sleepsend = account->c35_sleepsend;
1046 cl->monlvl = account->monlvl;
1047 cl->disabled = account->disabled;
1048 cl->fchid = account->fchid; // CHID filters
1049 cl->cltab = account->cltab; // Class
1050 // newcamd module doesn't like ident reloading
1051 if(!cl->ncd_server)
1052 cl->ftab = account->ftab; // Ident
1053
1054 cl->sidtabok = account->sidtabok; // services
1055 cl->sidtabno = account->sidtabno; // services
1056 cl->failban = account->failban;
1057
1058 memcpy(&cl->ctab, &account->ctab, sizeof(cl->ctab));
1059 memcpy(&cl->ttab, &account->ttab, sizeof(cl->ttab));
1060#ifdef WEBIF
1061 int32_t i;
1062 for(i = 0; i < CS_ECM_RINGBUFFER_MAX; i++) {
1063 cl->cwlastresptimes[i].duration = 0;
1064 cl->cwlastresptimes[i].timestamp = time((time_t*)0);
1065 cl->cwlastresptimes[i].rc = 0;
1066 }
1067 cl->cwlastresptimes_last = 0;
1068#endif
1069 if (account->uniq)
1070 cs_fake_client(cl, account->usr, (account->uniq == 1 || account->uniq == 2)?account->uniq+2:account->uniq, cl->ip);
1071#ifdef CS_ANTICASC
1072 int32_t numusers = account->ac_users;
1073 if ( numusers == -1)
1074 numusers = cfg.ac_users;
1075 cl->ac_limit = (numusers * 100 + 80) * cfg.ac_stime;
1076 cl->ac_penalty = account->ac_penalty == -1 ? cfg.ac_penalty : account->ac_penalty;
1077 cs_debug_mask(D_CLIENT, "acasc: client '%s', users=%d, stime=%d min, dwlimit=%d per min, penalty=%d",
1078 account->usr, numusers, cfg.ac_stime,
1079 numusers*100+80, cl->ac_penalty);
1080#endif
1081 }
1082 } else {
1083 if (ph[cl->ctyp].type & MOD_CONN_NET) {
1084 cs_debug_mask(D_TRACE, "client '%s', thread=%8lX not found in db (or password changed)", cl->account->usr, (unsigned long)cl->thread);
1085 kill_thread(cl);
1086 } else {
1087 cl->account = first_client->account;
1088 }
1089 }
1090 } else {
1091 cl->account = NULL;
1092 }
1093}
1094
1095struct s_client * create_client(in_addr_t ip) {
1096 struct s_client *cl;
1097
1098 if(cs_malloc(&cl, sizeof(struct s_client), -1)){
1099 //client part
1100 cl->ip=ip;
1101 cl->account = first_client->account;
1102
1103 //master part
1104 pthread_mutex_init(&cl->thread_lock, NULL);
1105
1106 cl->login=cl->last=time((time_t *)0);
1107
1108 cl->tid = (uint32_t)(uintptr_t)cl; // Use pointer adress of client as threadid (for monitor and log)
1109
1110 //Now add new client to the list:
1111 struct s_client *last;
1112 cs_writelock(&clientlist_lock);
1113 if(sizeof(uintptr_t) > 4){ // 64bit systems can have collisions because of the cast so lets check if there are some
1114 int8_t found;
1115 do{
1116 found = 0;
1117 for (last=first_client; last; last=last->next){
1118 if(last->tid == cl->tid){
1119 found = 1;
1120 break;
1121 }
1122 }
1123 if(found || cl->tid == 0){
1124 cl->tid = (uint32_t)rand();
1125 }
1126 } while (found || cl->tid == 0);
1127 }
1128 for (last=first_client; last->next != NULL; last=last->next); //ends with cl on last client
1129 last->next = cl;
1130 cs_writeunlock(&clientlist_lock);
1131 } else {
1132 cs_log("max connections reached (out of memory) -> reject client %s", cs_inet_ntoa(ip));
1133 return NULL;
1134 }
1135 return(cl);
1136}
1137
1138
1139/* Creates the master client of OSCam and inits some global variables/mutexes. */
1140static void init_first_client()
1141{
1142 // get username OScam is running under
1143 struct passwd pwd;
1144 char buf[256];
1145 struct passwd *pwdbuf;
1146 if ((getpwuid_r(getuid(), &pwd, buf, sizeof(buf), &pwdbuf)) == 0){
1147 if(cs_malloc(&processUsername, strlen(pwd.pw_name) + 1, -1))
1148 cs_strncpy(processUsername, pwd.pw_name, strlen(pwd.pw_name) + 1);
1149 else
1150 processUsername = "root";
1151 } else
1152 processUsername = "root";
1153
1154 if(!cs_malloc(&first_client, sizeof(struct s_client), -1)){
1155 fprintf(stderr, "Could not allocate memory for master client, exiting...");
1156 exit(1);
1157 }
1158 first_client->next = NULL; //terminate clients list with NULL
1159 first_client->login=time((time_t *)0);
1160 first_client->ip=cs_inet_addr("127.0.0.1");
1161 first_client->typ='s';
1162 first_client->thread=pthread_self();
1163 struct s_auth *null_account;
1164 if(!cs_malloc(&null_account, sizeof(struct s_auth), -1)){
1165 fprintf(stderr, "Could not allocate memory for master account, exiting...");
1166 exit(1);
1167 }
1168 first_client->account = null_account;
1169 if (pthread_setspecific(getclient, first_client)) {
1170 fprintf(stderr, "Could not setspecific getclient in master process, exiting...");
1171 exit(1);
1172 }
1173
1174#if defined(LIBUSB)
1175 cs_lock_create(&sr_lock, 10, "sr_lock");
1176#endif
1177 cs_lock_create(&system_lock, 5, "system_lock");
1178 cs_lock_create(&gethostbyname_lock, 10, "gethostbyname_lock");
1179 cs_lock_create(&clientlist_lock, 5, "clientlist_lock");
1180 cs_lock_create(&readerlist_lock, 5, "readerlist_lock");
1181 cs_lock_create(&fakeuser_lock, 5, "fakeuser_lock");
1182 cs_lock_create(&ecmcache_lock, 5, "ecmcache_lock");
1183 cs_lock_create(&readdir_lock, 5, "readdir_lock");
1184
1185#ifdef COOL
1186 coolapi_open_all();
1187#endif
1188}
1189
1190/* Checks if the date of the system is correct and waits if necessary. */
1191static void init_check(){
1192 char *ptr = __DATE__;
1193 int32_t month, year = atoi(ptr + strlen(ptr) - 4), day = atoi(ptr + 4);
1194 if(day > 0 && day < 32 && year > 2010 && year < 9999){
1195 struct tm timeinfo;
1196 char months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1197 for(month = 0; month < 12; ++month){
1198 if(!strncmp(ptr, months[month], 3)) break;
1199 }
1200 if(month > 11) month = 0;
1201 memset(&timeinfo, 0, sizeof(timeinfo));
1202 timeinfo.tm_mday = day;
1203 timeinfo.tm_mon = month;
1204 timeinfo.tm_year = year - 1900;
1205 time_t builddate = mktime(&timeinfo) - 86400;
1206 int32_t i = 0;
1207 while(time((time_t*)0) < builddate){
1208 if(i == 0) cs_log("The current system time is smaller than the build date (%s). Waiting up to %d seconds for time to correct", ptr, cs_waittime);
1209 cs_sleepms(1000);
1210 ++i;
1211 if(i > cs_waittime){
1212 cs_log("Waiting was not successful. OSCam will be started but is UNSUPPORTED this way. Do not report any errors with this version.");
1213 break;
1214 }
1215 }
1216 // adjust login time of first client
1217 if(i > 0) first_client->login=time((time_t *)0);
1218 }
1219}
1220
1221static int32_t start_listener(struct s_module *ph, int32_t port_idx)
1222{
1223 int32_t ov=1, timeout, is_udp, i;
1224 char ptxt[2][32];
1225 struct sockaddr_in sad; /* structure to hold server's address */
1226 cs_log("Starting listener %d", port_idx);
1227
1228 ptxt[0][0]=ptxt[1][0]='\0';
1229 if (!ph->ptab->ports[port_idx].s_port)
1230 {
1231 cs_log("%s: disabled", ph->desc);
1232 return(0);
1233 }
1234 is_udp=(ph->type==MOD_CONN_UDP);
1235
1236 memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
1237 sad.sin_family = AF_INET; /* set family to Internet */
1238 if (!ph->s_ip)
1239 ph->s_ip=cfg.srvip;
1240 if (ph->s_ip)
1241 {
1242 sad.sin_addr.s_addr=ph->s_ip;
1243 snprintf(ptxt[0], sizeof(ptxt[0]), ", ip=%s", inet_ntoa(sad.sin_addr));
1244 }
1245 else
1246 sad.sin_addr.s_addr=INADDR_ANY;
1247 timeout=cfg.bindwait;
1248 //ph->fd=0;
1249 ph->ptab->ports[port_idx].fd = 0;
1250
1251 if (ph->ptab->ports[port_idx].s_port > 0) /* test for illegal value */
1252 sad.sin_port = htons((uint16_t)ph->ptab->ports[port_idx].s_port);
1253 else
1254 {
1255 cs_log("%s: Bad port %d", ph->desc, ph->ptab->ports[port_idx].s_port);
1256 return(0);
1257 }
1258
1259 if ((ph->ptab->ports[port_idx].fd=socket(PF_INET,is_udp ? SOCK_DGRAM : SOCK_STREAM, is_udp ? IPPROTO_UDP : IPPROTO_TCP))<0)
1260 {
1261 cs_log("%s: Cannot create socket (errno=%d: %s)", ph->desc, errno, strerror(errno));
1262 return(0);
1263 }
1264
1265 ov=1;
1266 if (setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&ov, sizeof(ov))<0)
1267 {
1268 cs_log("%s: setsockopt failed (errno=%d: %s)", ph->desc, errno, strerror(errno));
1269 close(ph->ptab->ports[port_idx].fd);
1270 return(ph->ptab->ports[port_idx].fd=0);
1271 }
1272
1273#ifdef SO_REUSEPORT
1274 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEPORT, (void *)&ov, sizeof(ov));
1275#endif
1276
1277#ifdef SO_PRIORITY
1278 if (cfg.netprio)
1279 if (!setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg.netprio, sizeof(uint32_t)))
1280 snprintf(ptxt[1], sizeof(ptxt[1]), ", prio=%d", cfg.netprio);
1281#endif
1282
1283 if( !is_udp )
1284 {
1285 int32_t keep_alive = 1;
1286 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_KEEPALIVE,
1287 (void *)&keep_alive, sizeof(keep_alive));
1288 }
1289
1290 while (timeout--)
1291 {
1292 if (bind(ph->ptab->ports[port_idx].fd, (struct sockaddr *)&sad, sizeof (sad))<0)
1293 {
1294 if (timeout)
1295 {
1296 cs_log("%s: Bind request failed, waiting another %d seconds",
1297 ph->desc, timeout);
1298 cs_sleepms(1000);
1299 }
1300 else
1301 {
1302 cs_log("%s: Bind request failed, giving up", ph->desc);
1303 close(ph->ptab->ports[port_idx].fd);
1304 return(ph->ptab->ports[port_idx].fd=0);
1305 }
1306 }
1307 else timeout=0;
1308 }
1309
1310 if (!is_udp)
1311 if (listen(ph->ptab->ports[port_idx].fd, CS_QLEN)<0)
1312 {
1313 cs_log("%s: Cannot start listen mode (errno=%d: %s)", ph->desc, errno, strerror(errno));
1314 close(ph->ptab->ports[port_idx].fd);
1315 return(ph->ptab->ports[port_idx].fd=0);
1316 }
1317
1318 cs_log("%s: initialized (fd=%d, port=%d%s%s%s)",
1319 ph->desc, ph->ptab->ports[port_idx].fd,
1320 ph->ptab->ports[port_idx].s_port,
1321 ptxt[0], ptxt[1], ph->logtxt ? ph->logtxt : "");
1322
1323 for( i=0; i<ph->ptab->ports[port_idx].ftab.nfilts; i++ ) {
1324 int32_t j, pos=0;
1325 char buf[30 + (8*ph->ptab->ports[port_idx].ftab.filts[i].nprids)];
1326 pos += snprintf(buf, sizeof(buf), "-> CAID: %04X PROVID: ", ph->ptab->ports[port_idx].ftab.filts[i].caid );
1327
1328 for( j=0; j<ph->ptab->ports[port_idx].ftab.filts[i].nprids; j++ )
1329 pos += snprintf(buf+pos, sizeof(buf)-pos, "%06X, ", ph->ptab->ports[port_idx].ftab.filts[i].prids[j]);
1330
1331 if(pos>2 && j>0)
1332 buf[pos-2] = '\0';
1333
1334 cs_log("%s", buf);
1335 }
1336
1337 return(ph->ptab->ports[port_idx].fd);
1338}
1339
1340/* Resolves the ip of the hostname of the specified account and saves it in account->dynip.
1341 If the hostname is not configured, the ip is set to 0. */
1342void cs_user_resolve(struct s_auth *account){
1343 if (account->dyndns[0]){
1344 in_addr_t lastip = account->dynip;
1345 account->dynip = cs_getIPfromHost((char*)account->dyndns);
1346
1347 if (lastip != account->dynip) {
1348 cs_log("%s: resolved ip=%s", (char*)account->dyndns, cs_inet_ntoa(account->dynip));
1349 }
1350 } else account->dynip=0;
1351}
1352
1353/* Starts a thread named nameroutine with the start function startroutine. */
1354void start_thread(void * startroutine, char * nameroutine) {
1355 pthread_t temp;
1356 pthread_attr_t attr;
1357 pthread_attr_init(&attr);
1358 cs_log("starting thread %s", nameroutine);
1359#ifndef TUXBOX
1360 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
1361#endif
1362 cs_writelock(&system_lock);
1363 int32_t ret = pthread_create(&temp, &attr, startroutine, NULL);
1364 if (ret)
1365 cs_log("ERROR: can't create %s thread (errno=%d %s)", nameroutine, ret, strerror(ret));
1366 else {
1367 cs_log("%s thread started", nameroutine);
1368 pthread_detach(temp);
1369 }
1370 pthread_attr_destroy(&attr);
1371 cs_writeunlock(&system_lock);
1372}
1373
1374/* Allows to kill another thread specified through the client cl with locking.
1375 If the own thread has to be cancelled, cs_exit or cs_disconnect_client has to be used. */
1376void kill_thread(struct s_client *cl) {
1377 if (!cl || cl->kill) return;
1378 cl->kill=1;
1379 add_job(cl, ACTION_CLIENT_KILL, NULL, 0);
1380}
1381
1382/* Removes a reader from the list of active readers so that no ecms can be requested anymore. */
1383void remove_reader_from_active(struct s_reader *rdr) {
1384 struct s_reader *rdr2, *prv = NULL;
1385 //cs_log("CHECK: REMOVE READER %s FROM ACTIVE", rdr->label);
1386 cs_writelock(&readerlist_lock);
1387 for (rdr2=first_active_reader; rdr2 ; prv=rdr2, rdr2=rdr2->next) {
1388 if (rdr2==rdr) {
1389 if (prv) prv->next = rdr2->next;
1390 else first_active_reader = rdr2->next;
1391 break;
1392 }
1393 }
1394 rdr->next = NULL;
1395 cs_writeunlock(&readerlist_lock);
1396}
1397
1398/* Adds a reader to the list of active readers so that it can serve ecms. */
1399void add_reader_to_active(struct s_reader *rdr) {
1400 struct s_reader *rdr2, *rdr_prv=NULL, *rdr_tmp=NULL;
1401 int8_t at_first = 1;
1402
1403 if (rdr->next)
1404 remove_reader_from_active(rdr);
1405
1406 //cs_log("CHECK: ADD READER %s TO ACTIVE", rdr->label);
1407 cs_writelock(&readerlist_lock);
1408 cs_writelock(&clientlist_lock);
1409
1410 //search configured position:
1411 LL_ITER it = ll_iter_create(configured_readers);
1412 while ((rdr2=ll_iter_next(&it))) {
1413 if(rdr2==rdr) break;
1414 if (rdr2->client && rdr2->enable) {
1415 rdr_prv = rdr2;
1416 at_first = 0;
1417 }
1418 }
1419
1420 //insert at configured position:
1421 if (first_active_reader) {
1422 if (at_first) {
1423 rdr->next = first_active_reader;
1424 first_active_reader = rdr;
1425
1426 //resort client list:
1427 struct s_client *prev, *cl;
1428 for (prev = first_client, cl = first_client->next;
1429 prev->next != NULL; prev = prev->next, cl = cl->next)
1430 if (rdr->client == cl)
1431 break;
1432
1433 if (rdr->client == cl) {
1434 prev->next = cl->next; //remove client from list
1435 cl->next = first_client->next;
1436 first_client->next = cl;
1437 }
1438 }
1439 else
1440 {
1441 for (rdr2=first_active_reader; rdr2->next && rdr2 != rdr_prv ; rdr2=rdr2->next) ; //search last element
1442 rdr_prv = rdr2;
1443 rdr_tmp = rdr2->next;
1444 rdr2->next = rdr;
1445 rdr->next = rdr_tmp;
1446
1447 //resort client list:
1448 struct s_client *prev, *cl;
1449 for (prev = first_client, cl = first_client->next;
1450 prev->next != NULL; prev = prev->next, cl = cl->next)
1451 if (rdr->client == cl)
1452 break;
1453 if (rdr->client == cl) {
1454 prev->next = cl->next; //remove client from list
1455 cl->next = rdr_prv->client->next;
1456 rdr_prv->client->next = cl;
1457 }
1458 }
1459
1460 } else first_active_reader = rdr;
1461
1462 cs_writeunlock(&clientlist_lock);
1463 cs_writeunlock(&readerlist_lock);
1464}
1465
1466/* Starts or restarts a cardreader without locking. If restart=1, the existing thread is killed before restarting,
1467 if restart=0 the cardreader is only started. */
1468static int32_t restart_cardreader_int(struct s_reader *rdr, int32_t restart) {
1469 struct s_client *old_client = rdr->client;
1470 if (restart){
1471 remove_reader_from_active(rdr); //remove from list
1472 struct s_client *cl = rdr->client;
1473 if (cl) { //kill old thread
1474 kill_thread(cl);
1475 rdr->client = NULL;
1476 }
1477 }
1478
1479 while (restart && old_client && old_client->reader == rdr) {
1480 //If we quick disable+enable a reader (webif), remove_reader_from_active is called from
1481 //cleanup. this could happen AFTER reader is restarted, so oscam crashes or reader is hidden
1482 //cs_log("CHECK: WAITING FOR CLEANUP READER %s", rdr->label);
1483 cs_sleepms(100); //Fixme, cleanup does old_client->reader = NULL
1484 }
1485
1486 rdr->tcp_connected = 0;
1487 rdr->card_status = UNKNOWN;
1488 rdr->tcp_block_delay = 100;
1489 cs_ftime(&rdr->tcp_block_connect_till);
1490
1491 if (rdr->device[0] && (rdr->typ & R_IS_CASCADING)) {
1492 if (!rdr->ph.num) {
1493 cs_log("Protocol Support missing. (typ=%d)", rdr->typ);
1494 return 0;
1495 }
1496 cs_debug_mask(D_TRACE, "reader %s protocol: %s", rdr->label, rdr->ph.desc);
1497 }
1498
1499 if (!rdr->enable)
1500 return 0;
1501
1502 if (rdr->device[0]) {
1503 if (restart) {
1504 cs_log("restarting reader %s", rdr->label);
1505 }
1506 struct s_client * cl = create_client(first_client->ip);
1507 if (cl == NULL) return 0;
1508 cl->reader=rdr;
1509 cs_log("creating thread for device %s", rdr->device);
1510
1511 cl->sidtabok=rdr->sidtabok;
1512 cl->sidtabno=rdr->sidtabno;
1513 cl->grp = rdr->grp;
1514
1515 rdr->client=cl;
1516
1517 cl->typ='r';
1518 //client[i].ctyp=99;
1519
1520 add_job(cl, ACTION_READER_INIT, NULL, 0);
1521 add_reader_to_active(rdr);
1522
1523 return 1;
1524 }
1525 return 0;
1526}
1527
1528/* Starts or restarts a cardreader with locking. If restart=1, the existing thread is killed before restarting,
1529 if restart=0 the cardreader is only started. */
1530int32_t restart_cardreader(struct s_reader *rdr, int32_t restart) {
1531 cs_writelock(&system_lock);
1532 int32_t result = restart_cardreader_int(rdr, restart);
1533 cs_writeunlock(&system_lock);
1534 return result;
1535}
1536
1537static void init_cardreader() {
1538
1539 cs_debug_mask(D_TRACE, "cardreader: Initializing");
1540 cs_writelock(&system_lock);
1541 struct s_reader *rdr;
1542
1543#ifdef WITH_CARDREADER
1544 ICC_Async_Init_Locks();
1545#endif
1546
1547 LL_ITER itr = ll_iter_create(configured_readers);
1548 while((rdr = ll_iter_next(&itr))) {
1549 if (rdr->enable) {
1550 restart_cardreader_int(rdr, 0);
1551 }
1552 }
1553
1554#ifdef WITH_LB
1555 load_stat_from_file();
1556#endif
1557 cs_writeunlock(&system_lock);
1558}
1559
1560static void cs_fake_client(struct s_client *client, char *usr, int32_t uniq, in_addr_t ip)
1561{
1562 /* Uniq = 1: only one connection per user
1563 *
1564 * Uniq = 2: set (new connected) user only to fake if source
1565 * ip is different (e.g. for newcamd clients with
1566 * different CAID's -> Ports)
1567 *
1568 * Uniq = 3: only one connection per user, but only the last
1569 * login will survive (old mpcs behavior)
1570 *
1571 * Uniq = 4: set user only to fake if source ip is
1572 * different, but only the last login will survive
1573 */
1574
1575 struct s_client *cl;
1576 struct s_auth *account;
1577 cs_writelock(&fakeuser_lock);
1578 for (cl=first_client->next; cl ; cl=cl->next)
1579 {
1580 account = cl->account;
1581 if (cl != client && (cl->typ == 'c') && !cl->dup && account && !strcmp(account->usr, usr)
1582 && (uniq < 5) && ((uniq % 2) || (cl->ip != ip)))
1583 {
1584 char buf[20];
1585 if (uniq == 3 || uniq == 4)
1586 {
1587 cl->dup = 1;
1588 cl->aureader_list = NULL;
1589 cs_strncpy(buf, cs_inet_ntoa(cl->ip), sizeof(buf));
1590 cs_log("client(%8lX) duplicate user '%s' from %s (prev %s) set to fake (uniq=%d)",
1591 (unsigned long)cl->thread, usr, cs_inet_ntoa(ip), buf, uniq);
1592 if (cl->failban & BAN_DUPLICATE) {
1593 cs_add_violation(cl, usr);
1594 }
1595 if (cfg.dropdups){
1596 cs_writeunlock(&fakeuser_lock);
1597 kill_thread(cl);
1598 cs_writelock(&fakeuser_lock);
1599 }
1600 }
1601 else
1602 {
1603 client->dup = 1;
1604 client->aureader_list = NULL;
1605 cs_strncpy(buf, cs_inet_ntoa(ip), sizeof(buf));
1606 cs_log("client(%8lX) duplicate user '%s' from %s (current %s) set to fake (uniq=%d)",
1607 (unsigned long)pthread_self(), usr, cs_inet_ntoa(cl->ip), buf, uniq);
1608 if (client->failban & BAN_DUPLICATE) {
1609 cs_add_violation_by_ip(ip, ph[client->ctyp].ptab->ports[client->port_idx].s_port, usr);
1610 }
1611 if (cfg.dropdups){
1612 cs_writeunlock(&fakeuser_lock); // we need to unlock here as cs_disconnect_client kills the current thread!
1613 cs_disconnect_client(client);
1614 }
1615 break;
1616 }
1617 }
1618 }
1619 cs_writeunlock(&fakeuser_lock);
1620}
1621
1622int32_t cs_auth_client(struct s_client * client, struct s_auth *account, const char *e_txt)
1623{
1624 int32_t rc=0;
1625 unsigned char md5tmp[MD5_DIGEST_LENGTH];
1626 char buf[32];
1627 char *t_crypt="encrypted";
1628 char *t_plain="plain";
1629 char *t_grant=" granted";
1630 char *t_reject=" rejected";
1631 char *t_msg[]= { buf, "invalid access", "invalid ip", "unknown reason", "protocol not allowed" };
1632 memset(&client->grp, 0xff, sizeof(uint64_t));
1633 //client->grp=0xffffffffffffff;
1634 if ((intptr_t)account != 0 && (intptr_t)account != -1 && account->disabled){
1635 cs_add_violation(client, account->usr);
1636 cs_log("%s %s-client %s%s (%s%sdisabled account)",
1637 client->crypted ? t_crypt : t_plain,
1638 ph[client->ctyp].desc,
1639 client->ip ? cs_inet_ntoa(client->ip) : "",
1640 client->ip ? t_reject : t_reject+1,
1641 e_txt ? e_txt : "",
1642 e_txt ? " " : "");
1643 return(1);
1644 }
1645
1646 // check whether client comes in over allowed protocol
1647 if ((intptr_t)account != 0 && (intptr_t)account != -1 && (intptr_t)account->allowedprotocols &&
1648 (((intptr_t)account->allowedprotocols & ph[client->ctyp].listenertype) != ph[client->ctyp].listenertype )){
1649 cs_add_violation(client, account->usr);
1650 cs_log("%s %s-client %s%s (%s%sprotocol not allowed)",
1651 client->crypted ? t_crypt : t_plain,
1652 ph[client->ctyp].desc,
1653 client->ip ? cs_inet_ntoa(client->ip) : "",
1654 client->ip ? t_reject : t_reject+1,
1655 e_txt ? e_txt : "",
1656 e_txt ? " " : "");
1657 return(1);
1658 }
1659
1660 client->account=first_client->account;
1661 switch((intptr_t)account)
1662 {
1663 case 0: // reject access
1664 rc=1;
1665 cs_add_violation(client, NULL);
1666 cs_log("%s %s-client %s%s (%s)",
1667 client->crypted ? t_crypt : t_plain,
1668 ph[client->ctyp].desc,
1669 client->ip ? cs_inet_ntoa(client->ip) : "",
1670 client->ip ? t_reject : t_reject+1,
1671 e_txt ? e_txt : t_msg[rc]);
1672 break;
1673 default: // grant/check access
1674 if (client->ip && account->dyndns[0]) {
1675 if (client->ip != account->dynip)
1676 cs_user_resolve(account);
1677 if (client->ip != account->dynip) {
1678 cs_add_violation(client, account->usr);
1679 rc=2;
1680 }
1681 }
1682
1683 client->monlvl=account->monlvl;
1684 client->account = account;
1685 if (!rc)
1686 {
1687 client->dup=0;
1688 if (client->typ=='c' || client->typ=='m')
1689 client->pcrc = crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), md5tmp), MD5_DIGEST_LENGTH);
1690 if (client->typ=='c')
1691 {
1692 client->last_caid = 0xFFFE;
1693 client->last_srvid = 0xFFFE;
1694 client->expirationdate = account->expirationdate;
1695 client->disabled = account->disabled;
1696 client->allowedtimeframe[0] = account->allowedtimeframe[0];
1697 client->allowedtimeframe[1] = account->allowedtimeframe[1];
1698 if(account->firstlogin == 0) account->firstlogin = time((time_t*)0);
1699 client->failban = account->failban;
1700 client->c35_suppresscmd08 = account->c35_suppresscmd08;
1701 client->ncd_keepalive = account->ncd_keepalive;
1702 client->grp = account->grp;
1703 client->aureader_list = account->aureader_list;
1704 client->autoau = account->autoau;
1705 client->tosleep = (60*account->tosleep);
1706 client->c35_sleepsend = account->c35_sleepsend;
1707 memcpy(&client->ctab, &account->ctab, sizeof(client->ctab));
1708 if (account->uniq)
1709 cs_fake_client(client, account->usr, account->uniq, client->ip);
1710 client->ftab = account->ftab; // IDENT filter
1711 client->cltab = account->cltab; // CLASS filter
1712 client->fchid = account->fchid; // CHID filter
1713 client->sidtabok= account->sidtabok; // services
1714 client->sidtabno= account->sidtabno; // services
1715 memcpy(&client->ttab, &account->ttab, sizeof(client->ttab));
1716#ifdef CS_ANTICASC
1717 ac_init_client(client, account);
1718#endif
1719 }
1720 }
1721 case -1: // anonymous grant access
1722 if (rc)
1723 t_grant=t_reject;
1724 else {
1725 if (client->typ=='m')
1726 snprintf(t_msg[0], sizeof(buf), "lvl=%d", client->monlvl);
1727 else {
1728 int32_t rcount = ll_count(client->aureader_list);
1729 snprintf(buf, sizeof(buf), "au=");
1730 if (!rcount)
1731 snprintf(buf+3, sizeof(buf)-3, "off");
1732 else {
1733 if (client->autoau)
1734 snprintf(buf+3, sizeof(buf)-3, "auto (%d reader)", rcount);
1735 else
1736 snprintf(buf+3, sizeof(buf)-3, "on (%d reader)", rcount);
1737 }
1738 }
1739 }
1740
1741 cs_log("%s %s-client %s%s (%s, %s)",
1742 client->crypted ? t_crypt : t_plain,
1743 e_txt ? e_txt : ph[client->ctyp].desc,
1744 client->ip ? cs_inet_ntoa(client->ip) : "",
1745 client->ip ? t_grant : t_grant+1,
1746 username(client), t_msg[rc]);
1747
1748 break;
1749 }
1750 return(rc);
1751}
1752
1753void cs_disconnect_client(struct s_client * client)
1754{
1755 char buf[32]={0};
1756 if (client->ip)
1757 snprintf(buf, sizeof(buf), " from %s", cs_inet_ntoa(client->ip));
1758 cs_log("%s disconnected %s", username(client), buf);
1759 if (client == cur_client())
1760 cs_exit(0);
1761 else
1762 kill_thread(client);
1763}
1764
1765#ifdef CS_CACHEEX
1766static void cs_cache_push_to_client(struct s_client *cl, ECM_REQUEST *er)
1767{
1768 ECM_REQUEST *erc = cs_malloc(&erc, sizeof(ECM_REQUEST), 0);
1769 memcpy(erc, er, sizeof(ECM_REQUEST));
1770 add_job(cl, ACTION_CACHE_PUSH_OUT, erc, sizeof(ECM_REQUEST));
1771}
1772
1773/**
1774 * cacheex modes:
1775 *
1776 * cacheex=1 CACHE PULL:
1777 * Situation: oscam A reader1 has cacheex=1, oscam B account1 has cacheex=1
1778 * oscam A gets a ECM request, reader1 send this request to oscam B, oscam B checks his cache
1779 * a. not found in cache: return NOK
1780 * a. found in cache: return OK+CW
1781 * b. not found in cache, but found pending request: wait max cacheexwaittime and check again
1782 * oscam B never requests new ECMs
1783 *
1784 * CW-flow: B->A
1785 *
1786 * cacheex=2 CACHE PUSH:
1787 * Situation: oscam A reader1 has cacheex=2, oscam B account1 has cacheex=2
1788 * if oscam B gets a CW, its pushed to oscam A
1789 * reader has normal functionality and can request ECMs
1790 *
1791 * Problem: oscam B can only push if oscam A is connected
1792 * Problem or feature?: oscam A reader can request ecms from oscam B
1793 *
1794 * CW-flow: B->A
1795 *
1796 * cacheex=3 REVERSE CACHE PUSH:
1797 * Situation: oscam A reader1 has cacheex=3, oscam B account1 has cacheex=3
1798 * if oscam A gets a CW, its pushed to oscam B
1799 *
1800 * oscam A never requests new ECMs
1801 *
1802 * CW-flow: A->B
1803 */
1804void cs_cache_push(ECM_REQUEST *er)
1805{
1806 if (er->rc >= E_NOTFOUND && er->rc != E_UNHANDLED) //Maybe later we could support other rcs
1807 return; //NOT FOUND/Invalid
1808
1809 if (er->cacheex_pushed || (er->ecmcacheptr && er->ecmcacheptr->cacheex_pushed))
1810 return;
1811
1812 //cacheex=2 mode: push (server->remote)
1813 struct s_client *cl;
1814 for (cl=first_client->next; cl; cl=cl->next) {
1815 if (er->cacheex_src != cl) {
1816 if (cl->typ == 'c' && !cl->dup && cl->account && cl->account->cacheex == 2) { //send cache over user
1817 if (ph[cl->ctyp].c_cache_push // cache-push able
1818 && (!er->grp || (cl->grp & er->grp)) //Group-check
1819 && chk_srvid(cl, er) //Service-check
1820 && (chk_caid(er->caid, &cl->ctab) > 0)) //Caid-check
1821 {
1822 if(ph[cl->ctyp].c_cache_push_chk)
1823 if (!ph[cl->ctyp].c_cache_push_chk(cl, er))
1824 continue;
1825
1826 cs_cache_push_to_client(cl, er);
1827 }
1828 }
1829 }
1830 }
1831
1832 //cacheex=3 mode: reverse push (reader->server)
1833 struct s_reader *rdr;
1834 for (rdr = first_active_reader; rdr; rdr = rdr->next) {
1835 struct s_client *cl = rdr->client;
1836 if (cl && er->cacheex_src != cl && rdr->cacheex == 3) { //send cache over reader
1837 if (rdr->ph.c_cache_push
1838 && (!er->grp || (rdr->grp & er->grp)) //Group-check
1839 && chk_srvid(cl, er) //Service-check
1840 && chk_ctab(er->caid, &rdr->ctab)) //Caid-check
1841 {
1842 // cc-nodeid-list-check
1843 if(rdr->ph.c_cache_push_chk)
1844 if (!rdr->ph.c_cache_push_chk(cl, er))
1845 continue;
1846
1847 cs_cache_push_to_client(cl, er);
1848 }
1849 }
1850 }
1851
1852 er->cacheex_pushed = 1;
1853 if (er->ecmcacheptr) er->ecmcacheptr->cacheex_pushed = 1;
1854}
1855
1856static int8_t is_match_alias(struct s_client *cl, ECM_REQUEST *er)
1857{
1858 return cl && cl->account && cl->account->cacheex == 1 && is_cacheex_matcher_matching(NULL, er);
1859}
1860
1861static int8_t match_alias(struct s_client *cl, ECM_REQUEST *er, ECM_REQUEST *ecm)
1862{
1863 if (cl && cl->account && cl->account->cacheex == 1) {
1864 struct s_cacheex_matcher *entry = is_cacheex_matcher_matching(ecm, er);
1865 if (entry) {
1866 int32_t diff = comp_timeb(&er->tps, &ecm->tps);
1867 if (diff > entry->valid_from && diff < entry->valid_to) {
1868 cs_debug_mask(D_CACHEEX, "cacheex-matching for: %04X:%06X:%04X:%04X:%04X:%02X = %04X:%06X:%04X:%04X:%04X:%02X valid %d/%d",
1869 entry->caid, entry->provid, entry->srvid, entry->pid, entry->chid, entry->ecmlen,
1870 entry->to_caid, entry->to_provid, entry->to_srvid, entry->to_pid, entry->to_chid, entry->to_ecmlen,
1871 entry->valid_from, entry->valid_to);
1872 return 1;
1873 }
1874 }
1875 }
1876 return 0;
1877}
1878#endif
1879
1880/**
1881 * ecm cache
1882 **/
1883struct ecm_request_t *check_cwcache(ECM_REQUEST *er, struct s_client *cl)
1884{
1885 time_t now = time(NULL);
1886 //time_t timeout = now-(time_t)(cfg.ctimeout/1000)-CS_CACHE_TIMEOUT;
1887 time_t timeout = now-cfg.max_cache_time;
1888 struct ecm_request_t *ecm;
1889 uint64_t grp = cl?cl->grp:0;
1890
1891 cs_readlock(&ecmcache_lock);
1892 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
1893 if (ecm->tps.time < timeout) {
1894 ecm = NULL;
1895 break;
1896 }
1897
1898 if ((grp && ecm->grp && !(grp & ecm->grp)))
1899 continue;
1900
1901#ifdef CS_CACHEEX
1902 if (!match_alias(cl, er, ecm)) {
1903#endif
1904 if (!(ecm->caid == er->caid || (ecm->ocaid && er->ocaid && ecm->ocaid == er->ocaid)))
1905 continue;
1906
1907#ifdef CS_CACHEEX
1908 //CWs from csp have no ecms, so ecm->l=0. ecmd5 is invalid, so do not check!
1909 if (ecm->csp_hash != er->csp_hash)
1910 continue;
1911
1912 if (ecm->l > 0 && memcmp(ecm->ecmd5, er->ecmd5, CS_ECMSTORESIZE))
1913 continue;
1914
1915#else
1916 if (memcmp(ecm->ecmd5, er->ecmd5, CS_ECMSTORESIZE))
1917 continue;
1918#endif
1919#ifdef CS_CACHEEX
1920 }
1921#endif
1922
1923 if (ecm->rc != E_99)
1924 break;
1925 }
1926 cs_readunlock(&ecmcache_lock);
1927 return ecm;
1928}
1929
1930/*
1931 * write_ecm_request():
1932 */
1933static int32_t write_ecm_request(struct s_reader *rdr, ECM_REQUEST *er)
1934{
1935 add_job(rdr->client, ACTION_READER_ECM_REQUEST, (void*)er, 0);
1936 return 1;
1937}
1938
1939
1940/**
1941 * distributes found ecm-request to all clients with rc=99
1942 **/
1943static void distribute_ecm(ECM_REQUEST *er, int32_t rc)
1944{
1945 struct ecm_request_t *ecm;
1946
1947 cs_readlock(&ecmcache_lock);
1948 for (ecm = ecmcwcache; ecm; ecm = ecm->next) {
1949 if (ecm != er && ecm->rc >= E_99 && ecm->ecmcacheptr == er) {
1950#ifdef CS_CACHEEX
1951 if (!ecm->cacheex_src)
1952 ecm->cacheex_src = er->cacheex_src;
1953#endif
1954 write_ecm_answer(er->selected_reader, ecm, rc, 0, er->cw, NULL);
1955 }
1956 }
1957 cs_readunlock(&ecmcache_lock);
1958}
1959
1960#ifdef CS_CACHEEX
1961static int8_t cs_add_cache_int(struct s_client *cl, ECM_REQUEST *er, int8_t csp)
1962{
1963 if (!cl)
1964 return 0;
1965 if (!csp && cl->reader && cl->reader->cacheex!=2) { //from reader
1966 cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
1967 return 0;
1968 }
1969 if (!csp && !cl->reader && cl->account && cl->account->cacheex!=3) { //from user
1970 cs_debug_mask(D_CACHEEX, "CACHEX received, but disabled for %s", username(cl));
1971 return 0;
1972 }
1973 if (!csp && !cl->reader && !cl->account) { //not active!
1974 cs_debug_mask(D_CACHEEX, "CACHEX received, but invalid client state %s", username(cl));
1975 return 0;
1976 }
1977
1978 if (er->rc < E_NOTFOUND) { //=FOUND Check CW:
1979 uint8_t i, c;
1980 for (i = 0; i < 16; i += 4) {
1981 c = ((er->cw[i] + er->cw[i + 1] + er->cw[i + 2]) & 0xff);
1982 if (er->cw[i + 3] != c) {
1983 cs_ddump_mask(D_CACHEEX, er->cw, 16,
1984 "push received cw with chksum error from %s", csp?"csp":username(cl));
1985 return 0;
1986 }
1987 }
1988
1989 //Check for NULL CWs:
1990 for (c=i=0; !c && i < 16; i++) {
1991 c = er->cw[i];
1992 }
1993 if (!c) {
1994 cs_ddump_mask(D_CACHEEX, er->cw, 16,
1995 "push received null cw from %s", csp?"csp":username(cl));
1996 return 0;
1997 }
1998 }
1999
2000 er->grp = cl->grp;
2001// er->ocaid = er->caid;
2002 if (er->rc < E_NOTFOUND) //map FOUND to CACHEEX
2003 er->rc = E_CACHEEX;
2004 er->cacheex_src = cl;
2005 er->client = NULL; //No Owner! So no fallback!
2006
2007 if (er->l) {
2008 uint16_t *lp;
2009 for (lp=(uint16_t *)er->ecm+(er->l>>2), er->checksum=0; lp>=(uint16_t *)er->ecm; lp--)
2010 er->checksum^=*lp;
2011
2012 int32_t offset = 3;
2013 if ((er->caid >> 8) == 0x17)
2014 offset = 13;
2015 unsigned char md5tmp[MD5_DIGEST_LENGTH];
2016 memcpy(er->ecmd5, MD5(er->ecm+offset, er->l-offset, md5tmp), CS_ECMSTORESIZE);
2017 er->csp_hash = csp_ecm_hash(er);
2018 //csp has already initialized these hashcode
2019 }
2020
2021
2022 if( (er->caid & 0xFF00) == 0x600 && !er->chid && er->l > 7)
2023 er->chid = (er->ecm[6]<<8)|er->ecm[7];
2024
2025 struct ecm_request_t *ecm = check_cwcache(er, cl);
2026
2027 if (!ecm) {
2028 cs_writelock(&ecmcache_lock);
2029 er->next = ecmcwcache;
2030 ecmcwcache = er;
2031 cs_writeunlock(&ecmcache_lock);
2032
2033 er->selected_reader = cl->reader;
2034
2035 cs_cache_push(er); //cascade push!
2036
2037 if (er->rc < E_NOTFOUND)
2038 cs_add_cacheex_stats(cl, er->caid, er->srvid, er->prid, 1);
2039
2040 cl->cwcacheexgot++;
2041 if (cl->account)
2042 cl->account->cwcacheexgot++;
2043 first_client->cwcacheexgot++;
2044
2045 cs_debug_mask(D_CACHEEX, "got pushed ECM %04X&%06X/%04X/%04X/%02X:%04X from %s",
2046 er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum), csp?"csp":username(cl));
2047
2048 return 1;
2049 }
2050 else {
2051 if(er->rc < ecm->rc) {
2052 if (ecm->csp_lastnodes == NULL) {
2053 ecm->csp_lastnodes = er->csp_lastnodes;
2054 er->csp_lastnodes = NULL;
2055 }
2056 ecm->cacheex_src = cl;
2057 ecm->cacheex_pushed = 0;
2058
2059 write_ecm_answer(cl->reader, ecm, er->rc, er->rcEx, er->cw, ecm->msglog);
2060
2061 cs_cache_push(ecm); //cascade push!
2062
2063 if (er->rc < E_NOTFOUND) {
2064 ecm->selected_reader = cl->reader;
2065 cs_add_cacheex_stats(cl, er->caid, er->srvid, er->prid, 1);
2066 }
2067
2068 cl->cwcacheexgot++;
2069 if (cl->account)
2070 cl->account->cwcacheexgot++;
2071 first_client->cwcacheexgot++;
2072
2073 cs_debug_mask(D_CACHEEX, "replaced pushed ECM %04X&%06X/%04X/%04X/%02X:%04X from %s",
2074 er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum), csp?"csp":username(cl));
2075 }
2076 else
2077 {
2078 cs_debug_mask(D_CACHEEX, "ignored duplicate pushed ECM %04X&%06X/%04X/%04X/%02X:%04X from %s",
2079 er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum), csp?"csp":username(cl));
2080 }
2081
2082 return 0;
2083 }
2084}
2085
2086void cs_add_cache(struct s_client *cl, ECM_REQUEST *er, int8_t csp)
2087{
2088 if (!cs_add_cache_int(cl, er, csp))
2089 free_ecm(er);
2090}
2091
2092#endif
2093
2094
2095int32_t write_ecm_answer(struct s_reader * reader, ECM_REQUEST *er, int8_t rc, uint8_t rcEx, uchar *cw, char *msglog)
2096{
2097 int32_t i;
2098 uchar c;
2099 struct s_ecm_answer *ea = NULL, *ea_list, *ea_org = NULL;
2100 int32_t diff, maxdiff = (int32_t)cfg.ctimeout+1000;
2101 struct timeb now;
2102 cs_ftime(&now);
2103
2104 if ((diff=comp_timeb(&now, &er->tps))>maxdiff) { // drop real old answers, because er->parent is dropped !
2105#ifdef WITH_DEBUG
2106 if (diff > (int32_t)cfg.max_cache_time*1000)
2107 cs_log("dropped old reader answer rc=%d from %s time %dms",
2108 rc, reader?reader->label:"undef", diff);
2109#endif
2110#ifdef WITH_LB
2111 send_reader_stat(reader, er, NULL, E_TIMEOUT);
2112#endif
2113 return 0;
2114 }
2115
2116 if (er->parent) {
2117 // parent is only set on reader->client->ecmtask[], but we want client->ecmtask[]
2118 // this means: reader has a ecm copy from client, so point to client
2119 er->rc = rc;
2120 er->idx = 0;
2121 er = er->parent; //Now er is "original" ecm, before it was the reader-copy
2122
2123 if (er->rc < E_99) {
2124#ifdef WITH_LB
2125 send_reader_stat(reader, er, NULL, rc);
2126#endif
2127 return 0; //Already done
2128 }
2129 }
2130
2131 for(ea_list = er->matching_rdr; reader && ea_list && !ea_org; ea_list = ea_list->next) {
2132 if (ea_list->reader == reader)
2133 ea_org = ea_list;
2134 }
2135
2136 if (!ea_org)
2137 ea = cs_malloc(&ea, sizeof(struct s_ecm_answer), 0); //Free by ACTION_CLIENT_ECM_ANSWER!
2138 else
2139 ea = ea_org;
2140
2141 if (cw)
2142 memcpy(ea->cw, cw, 16);
2143
2144 if (msglog)
2145 memcpy(ea->msglog, msglog, MSGLOGSIZE);
2146
2147 ea->rc = rc;
2148 ea->rcEx = rcEx;
2149 ea->reader = reader;
2150 ea->status |= REQUEST_ANSWERED;
2151 ea->er = er;
2152
2153 if (reader && rc<E_NOTFOUND) {
2154 if (reader->disablecrccws == 0) {
2155 for (i=0; i<16; i+=4) {
2156 c=((ea->cw[i]+ea->cw[i+1]+ea->cw[i+2]) & 0xff);
2157 if (ea->cw[i+3]!=c) {
2158 if (reader->dropbadcws) {
2159 ea->rc = E_NOTFOUND;
2160 ea->rcEx = E2_WRONG_CHKSUM;
2161 break;
2162 } else {
2163 cs_debug_mask(D_TRACE, "notice: changed dcw checksum byte cw[%i] from %02x to %02x", i+3, ea->cw[i+3],c);
2164 ea->cw[i+3]=c;
2165 }
2166 }
2167 }
2168 }
2169 else {
2170 cs_debug_mask(D_TRACE, "notice: CW checksum check disabled");
2171 }
2172 }
2173
2174 if (reader && ea->rc==E_FOUND) {
2175 /* CWL logging only if cwlogdir is set in config */
2176 if (cfg.cwlogdir != NULL)
2177 logCWtoFile(er, ea->cw);
2178 }
2179
2180 int32_t res = 0;
2181 struct s_client *cl = er->client;
2182 if (cl && !cl->kill) {
2183 if (ea_org) { //duplicate for queue
2184 ea = cs_malloc(&ea, sizeof(struct s_ecm_answer), 0);
2185 memcpy(ea, ea_org, sizeof(struct s_ecm_answer));
2186 }
2187 add_job(cl, ACTION_CLIENT_ECM_ANSWER, ea, sizeof(struct s_ecm_answer));
2188 res = 1;
2189 } else { //client has disconnected. Distribute ecms to other waiting clients
2190 if (!er->ecmcacheptr)
2191 chk_dcw(NULL, ea);
2192 if (!ea_org)
2193 free(ea);
2194 }
2195
2196 if (reader && rc == E_FOUND && reader->resetcycle > 0)
2197 {
2198 reader->resetcounter++;
2199 if (reader->resetcounter > reader->resetcycle) {
2200 reader->resetcounter = 0;
2201 cs_log("resetting reader %s resetcyle of %d ecms reached", reader->label, reader->resetcycle);
2202 reader->card_status = CARD_NEED_INIT;
2203#ifdef WITH_CARDREADER
2204 reader_reset(reader);
2205#endif
2206 }
2207 }
2208
2209 return res;
2210}
2211
2212ECM_REQUEST *get_ecmtask()
2213{
2214 ECM_REQUEST *er = NULL;
2215 struct s_client *cl = cur_client();
2216 if(!cl) return NULL;
2217
2218 if(!cs_malloc(&er,sizeof(ECM_REQUEST), -1)) return NULL;
2219
2220 cs_ftime(&er->tps);
2221 er->rc=E_UNHANDLED;
2222 er->client=cl;
2223 er->grp = cl->grp;
2224 //cs_log("client %s ECMTASK %d multi %d ctyp %d", username(cl), n, (ph[cl->ctyp].multi)?CS_MAXPENDING:1, cl->ctyp);
2225
2226 return(er);
2227}
2228
2229#ifdef WITH_LB
2230void send_reader_stat(struct s_reader *rdr, ECM_REQUEST *er, struct s_ecm_answer *ea, int8_t rc)
2231{
2232#ifdef CS_CACHEEX
2233 if (!rdr || rc>=E_99 || rdr->cacheex==1 || !rdr->client)
2234 return;
2235#else
2236 if (!rdr || rc>=E_99 || !rdr->client)
2237 return;
2238#endif
2239 if (er->ecmcacheptr) //ignore cache answer
2240 return;
2241
2242 struct timeb tpe;
2243 cs_ftime(&tpe);
2244 int32_t time = 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm;
2245 if (time < 1)
2246 time = 1;
2247
2248 if (ea && (ea->status & READER_FALLBACK) && time > (int32_t)cfg.ftimeout)
2249 time = time - cfg.ftimeout;
2250
2251 add_stat(rdr, er, time, rc);
2252}
2253#endif
2254
2255/**
2256 * Check for NULL CWs
2257 * Return them as "NOT FOUND"
2258 **/
2259static void checkCW(ECM_REQUEST *er)
2260{
2261 int8_t i;
2262 for (i=0;i<16;i++)
2263 if (er->cw[i]) return;
2264 er->rc = E_NOTFOUND;
2265}
2266
2267static void add_cascade_data(struct s_client *client, ECM_REQUEST *er)
2268{
2269 if (!client->cascadeusers)
2270 client->cascadeusers = ll_create("cascade_data");
2271 LLIST *l = client->cascadeusers;
2272 LL_ITER it = ll_iter_create(l);
2273 time_t now = time(NULL);
2274 struct s_cascadeuser *cu;
2275 int8_t found=0;
2276 while ((cu=ll_iter_next(&it))) {
2277 if (er->caid==cu->caid && er->prid==cu->prid && er->srvid==cu->srvid) { //found it
2278 if (cu->time < now)
2279 cu->cwrate = now-cu->time;
2280 cu->time = now;
2281 found=1;
2282 }
2283 else if (cu->time+60 < now) // old
2284 ll_iter_remove_data(&it);
2285 }
2286 if (!found) { //add it if not found
2287 cu = cs_malloc(&cu, sizeof(struct s_cascadeuser), 0);
2288 cu->caid = er->caid;
2289 cu->prid = er->prid;
2290 cu->srvid = er->srvid;
2291 cu->time = now;
2292 ll_append(l, cu);
2293 }
2294}
2295
2296int32_t send_dcw(struct s_client * client, ECM_REQUEST *er)
2297{
2298 if (!client || client->kill || client->typ != 'c')
2299 return 0;
2300
2301 static const char *stxt[]={"found", "cache1", "cache2", "cache3",
2302 "not found", "timeout", "sleeping",
2303 "fake", "invalid", "corrupt", "no card", "expdate", "disabled", "stopped"};
2304 static const char *stxtEx[16]={"", "group", "caid", "ident", "class", "chid", "queue", "peer", "sid", "", "", "", "", "", "", ""};
2305 static const char *stxtWh[16]={"", "user ", "reader ", "server ", "lserver ", "", "", "", "", "", "", "", "" ,"" ,"", ""};
2306 char sby[32]="", sreason[32]="", schaninfo[32]="";
2307 char erEx[32]="";
2308 char uname[38]="";
2309 char channame[32];
2310 struct timeb tpe;
2311
2312 snprintf(uname,sizeof(uname)-1, "%s", username(client));
2313
2314 if (er->rc < E_NOTFOUND)
2315 checkCW(er);
2316
2317 struct s_reader *er_reader = er->selected_reader; //responding reader
2318
2319 if (er_reader) {
2320 // add marker to reader if ECM_REQUEST was betatunneled
2321 if(er->ocaid)
2322 snprintf(sby, sizeof(sby)-1, " by %s(btun %04X)", er_reader->label, er->ocaid);
2323 else
2324 snprintf(sby, sizeof(sby)-1, " by %s", er_reader->label);
2325 }
2326
2327 if (er->rc < E_NOTFOUND) er->rcEx=0;
2328 if (er->rcEx)
2329 snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4],
2330 stxtEx[er->rcEx&0xf]);
2331
2332 if(cfg.mon_appendchaninfo)
2333 snprintf(schaninfo, sizeof(schaninfo)-1, " - %s", get_servicename(client, er->srvid, er->caid, channame));
2334
2335 if(er->msglog[0])
2336 snprintf(sreason, sizeof(sreason)-1, " (%s)", er->msglog);
2337
2338 cs_ftime(&tpe);
2339 client->cwlastresptime = 1000 * (tpe.time-er->tps.time) + tpe.millitm-er->tps.millitm;
2340
2341#ifdef WEBIF
2342 cs_add_lastresponsetime(client, client->cwlastresptime,time((time_t*)0) ,er->rc); // add to ringbuffer
2343#endif
2344
2345 if (er_reader){
2346 struct s_client *er_cl = er_reader->client;
2347 if(er_cl){
2348 er_cl->cwlastresptime = client->cwlastresptime;
2349#ifdef WEBIF
2350 cs_add_lastresponsetime(er_cl, client->cwlastresptime,time((time_t*)0) ,er->rc);
2351#endif
2352 er_cl->last_srvidptr=client->last_srvidptr;
2353 }
2354 }
2355
2356#ifdef WEBIF
2357 if (er_reader) {
2358 if(er->rc == E_FOUND)
2359 cs_strncpy(client->lastreader, er_reader->label, sizeof(client->lastreader));
2360 else if (er->rc == E_CACHEEX)
2361 cs_strncpy(client->lastreader, "cache3", sizeof(client->lastreader));
2362 else if (er->rc < E_NOTFOUND)
2363 snprintf(client->lastreader, sizeof(client->lastreader)-1, "%s (cache)", er_reader->label);
2364 else
2365 cs_strncpy(client->lastreader, stxt[er->rc], sizeof(client->lastreader));
2366 }
2367 else
2368 cs_strncpy(client->lastreader, stxt[er->rc], sizeof(client->lastreader));
2369#endif
2370 client->last = time((time_t*)0);
2371
2372 //cs_debug_mask(D_TRACE, "CHECK rc=%d er->cacheex_src=%s", er->rc, username(er->cacheex_src));
2373 switch(er->rc) {
2374 case E_FOUND:
2375 client->cwfound++;
2376 client->account->cwfound++;
2377 first_client->cwfound++;
2378 break;
2379
2380 case E_CACHE1:
2381 case E_CACHE2:
2382 case E_CACHEEX:
2383 client->cwcache++;
2384 client->account->cwcache++;
2385 first_client->cwcache++;
2386#ifdef CS_CACHEEX
2387 if (er->cacheex_src) {
2388 er->cacheex_src->cwcacheexhit++;
2389 if (er->cacheex_src->account)
2390 er->cacheex_src->account->cwcacheexhit++;
2391 first_client->cwcacheexhit++;
2392 }
2393#endif
2394 break;
2395
2396 case E_NOTFOUND:
2397 case E_CORRUPT:
2398 case E_NOCARD:
2399 if (er->rcEx) {
2400 client->cwignored++;
2401 client->account->cwignored++;
2402 first_client->cwignored++;
2403 } else {
2404 client->cwnot++;
2405 client->account->cwnot++;
2406 first_client->cwnot++;
2407 }
2408 break;
2409
2410 case E_TIMEOUT:
2411 client->cwtout++;
2412 client->account->cwtout++;
2413 first_client->cwtout++;
2414 break;
2415
2416 default:
2417 client->cwignored++;
2418 client->account->cwignored++;
2419 first_client->cwignored++;
2420 }
2421
2422#ifdef CS_ANTICASC
2423 ac_chk(client, er, 1);
2424#endif
2425
2426 int32_t is_fake = 0;
2427 if (er->rc==E_FAKE) {
2428 is_fake = 1;
2429 er->rc=E_FOUND;
2430 }
2431
2432 if (cfg.double_check && er->rc < E_NOTFOUND && er->selected_reader) {
2433 if (er->checked == 0) {//First CW, save it and wait for next one
2434 er->checked = 1;
2435 er->origin_reader = er->selected_reader;
2436 memcpy(er->cw_checked, er->cw, sizeof(er->cw));
2437 cs_log("DOUBLE CHECK FIRST CW by %s idx %d cpti %d", er->origin_reader->label, er->idx, er->msgid);
2438 }
2439 else if (er->origin_reader != er->selected_reader) { //Second (or third and so on) cw. We have to compare
2440 if (memcmp(er->cw_checked, er->cw, sizeof(er->cw)) == 0) {
2441 er->checked++;
2442 cs_log("DOUBLE CHECKED! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->msgid);
2443 }
2444 else {
2445 cs_log("DOUBLE CHECKED NONMATCHING! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->msgid);
2446 }
2447 }
2448
2449 if (er->checked < 2) { //less as two same cw? mark as pending!
2450 er->rc = E_UNHANDLED;
2451 return 0;
2452 }
2453 }
2454
2455 ph[client->ctyp].send_dcw(client, er);
2456
2457 add_cascade_data(client, er);
2458
2459 if (is_fake)
2460 er->rc = E_FAKE;
2461
2462 if (er->reader_avail == 1) {
2463 cs_log("%s (%04X&%06X/%04X/%04X/%02X:%04X): %s (%d ms)%s %s%s",
2464 uname, er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum),
2465 er->rcEx?erEx:stxt[er->rc], client->cwlastresptime, sby, schaninfo, sreason);
2466 } else {
2467 cs_log("%s (%04X&%06X/%04X/%04X/%02X:%04X): %s (%d ms)%s (%d of %d)%s%s",
2468 uname, er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum),
2469 er->rcEx?erEx:stxt[er->rc], client->cwlastresptime, sby, er->reader_count, er->reader_avail, schaninfo, sreason);
2470 }
2471
2472 cs_ddump_mask (D_ATR, er->cw, 16, "cw:");
2473
2474#ifdef ARM
2475 if(!er->rc &&cfg.enableled == 1) cs_switch_led(LED2, LED_BLINK_OFF);
2476#endif
2477
2478#ifdef QBOXHD
2479 if(cfg.enableled == 2){
2480 if (er->rc < E_NOTFOUND) {
2481 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_MEDIUM);
2482 } else if (er->rc <= E_STOPPED) {
2483 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_MEDIUM);
2484 }
2485 }
2486#endif
2487
2488 return 0;
2489}
2490
2491/**
2492 * sends the ecm request to the readers
2493 * ECM_REQUEST er : the ecm
2494 * er->stage: 0 = no reader asked yet
2495 * 2 = ask only local reader (skipped without preferlocalcards)
2496 * 3 = ask any non fallback reader
2497 * 4 = ask fallback reader
2498 **/
2499static void request_cw(ECM_REQUEST *er)
2500{
2501 struct s_ecm_answer *ea;
2502 int8_t sent = 0;
2503
2504 if (er->stage >= 4) return;
2505
2506 while (1) {
2507 er->stage++;
2508
2509#ifndef CS_CACHEEX
2510 if (er->stage == 1)
2511 er->stage++;
2512#endif
2513 if (er->stage == 2 && !cfg.preferlocalcards)
2514 er->stage++;
2515
2516 for(ea = er->matching_rdr; ea; ea = ea->next) {
2517
2518 switch(er->stage) {
2519#ifdef CS_CACHEEX
2520 case 1:
2521 // Cache-Echange
2522 if ((ea->status & REQUEST_SENT) ||
2523 (ea->status & (READER_CACHEEX|READER_ACTIVE)) != (READER_CACHEEX|READER_ACTIVE))
2524 continue;
2525 break;
2526#endif
2527 case 2:
2528 // only local reader
2529 if ((ea->status & REQUEST_SENT) ||
2530 (ea->status & (READER_ACTIVE|READER_FALLBACK|READER_LOCAL)) != (READER_ACTIVE|READER_LOCAL))
2531 continue;
2532 break;
2533
2534 case 3:
2535 // any non fallback reader not asked yet
2536 if ((ea->status & REQUEST_SENT) ||
2537 (ea->status & (READER_ACTIVE|READER_FALLBACK)) != READER_ACTIVE)
2538 continue;
2539 break;
2540
2541 default:
2542 // only fallbacks
2543 if ((ea->status & REQUEST_SENT) ||
2544 (ea->status & READER_ACTIVE) != READER_ACTIVE)
2545 {
2546 if (er->reader_avail > 1) //do not resend to the same reader(s) if we have more than one reader
2547 continue;
2548 }
2549 break;
2550 }
2551
2552 struct s_reader *rdr = ea->reader;
2553 cs_debug_mask(D_TRACE, "request_cw stage=%d to reader %s ecm=%04X", er->stage, rdr?rdr->label:"", htons(er->checksum));
2554 write_ecm_request(ea->reader, er);
2555 ea->status |= REQUEST_SENT;
2556
2557 //set sent=1 only if reader is active/connected. If not, switch to next stage!
2558 if (!sent && rdr) {
2559 struct s_client *rcl = rdr->client;
2560 if(rcl){
2561 if (rcl->typ=='r' && rdr->card_status==CARD_INSERTED)
2562 sent = 1;
2563 else if (rcl->typ=='p' && (rdr->card_status==CARD_INSERTED ||rdr->tcp_connected))
2564 sent = 1;
2565 }
2566 }
2567 }
2568 if (sent || er->stage >= 4)
2569 break;
2570 }
2571}
2572
2573static void chk_dcw(struct s_client *cl, struct s_ecm_answer *ea)
2574{
2575 if (!ea || !ea->er)
2576 return;
2577
2578 ECM_REQUEST *ert = ea->er;
2579 struct s_ecm_answer *ea_list;
2580 struct s_reader *eardr = ea->reader;
2581 if(!ert)
2582 return;
2583
2584 if (eardr) {
2585 cs_debug_mask(D_TRACE, "ecm answer from reader %s for ecm %04X rc=%d", eardr->label, htons(ert->checksum), ea->rc);
2586 //cs_ddump_mask(D_TRACE, ea->cw, sizeof(ea->cw), "received cw from %s caid=%04X srvid=%04X hash=%08X",
2587 // eardr->label, ert->caid, ert->srvid, ert->csp_hash);
2588 //cs_ddump_mask(D_TRACE, ert->ecm, ert->l, "received cw for ecm from %s caid=%04X srvid=%04X hash=%08X",
2589 // eardr->label, ert->caid, ert->srvid, ert->csp_hash);
2590 }
2591
2592 ea->status |= REQUEST_ANSWERED;
2593
2594 if (eardr) {
2595 //Update reader stats:
2596 if (ea->rc == E_FOUND) {
2597 eardr->ecmsok++;
2598#ifdef CS_CACHEEX
2599 struct s_client *eacl = eardr?eardr->client:NULL; //reader is null on timeouts
2600 if (eardr->cacheex == 1 && !ert->cacheex_done && eacl) {
2601 eacl->cwcacheexgot++;
2602 cs_add_cacheex_stats(eacl, ea->er->caid, ea->er->srvid, ea->er->prid, 1);
2603 first_client->cwcacheexgot++;
2604 }
2605#endif
2606 }
2607 else if (ea->rc == E_NOTFOUND)
2608 eardr->ecmsnok++;
2609
2610 //Reader ECMs Health Try (by Pickser)
2611 if (eardr->ecmsok != 0 || eardr->ecmsnok != 0)
2612 {
2613 eardr->ecmshealthok = ((double) eardr->ecmsok / (eardr->ecmsok + eardr->ecmsnok)) * 100;
2614 eardr->ecmshealthnok = ((double) eardr->ecmsnok / (eardr->ecmsok + eardr->ecmsnok)) * 100;
2615 }
2616
2617 //Reader Dynamic Loadbalancer Try (by Pickser)
2618 /*
2619 * todo: config-option!
2620 *
2621#ifdef WITH_LB
2622 if (eardr->ecmshealthok >= 75) {
2623 eardr->lb_weight = 100;
2624 } else if (eardr->ecmshealthok >= 50) {
2625 eardr->lb_weight = 75;
2626 } else if (eardr->ecmshealthok >= 25) {
2627 eardr->lb_weight = 50;
2628 } else {
2629 eardr->lb_weight = 25;
2630 }
2631#endif
2632 */
2633 }
2634
2635 if (ert->rc<E_99) {
2636#ifdef WITH_LB
2637 send_reader_stat(eardr, ert, ea, ea->rc);
2638#endif
2639 return; // already done
2640 }
2641
2642 int32_t reader_left = 0, local_left = 0;
2643#ifdef CS_CACHEEX
2644 int8_t cacheex_left = 0;
2645#endif
2646
2647 switch (ea->rc) {
2648 case E_FOUND:
2649 case E_CACHE2:
2650 case E_CACHE1:
2651 case E_CACHEEX:
2652 memcpy(ert->cw, ea->cw, 16);
2653 ert->rcEx=0;
2654 ert->rc = ea->rc;
2655 ert->selected_reader = eardr;
2656 break;
2657 case E_TIMEOUT:
2658 ert->rc = E_TIMEOUT;
2659 ert->rcEx = 0;
2660 break;
2661 case E_NOTFOUND:
2662 ert->rcEx=ea->rcEx;
2663 cs_strncpy(ert->msglog, ea->msglog, sizeof(ert->msglog));
2664 ert->selected_reader = eardr;
2665 if (!ert->ecmcacheptr) {
2666#ifdef CS_CACHEEX
2667 uchar has_cacheex = 0;
2668#endif
2669 for(ea_list = ert->matching_rdr; ea_list; ea_list = ea_list->next) {
2670#ifdef CS_CACHEEX
2671 if (((ea_list->status & READER_CACHEEX)) == READER_CACHEEX)
2672 has_cacheex = 1;
2673 if (((ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED|READER_CACHEEX|READER_ACTIVE)) == (REQUEST_SENT|READER_CACHEEX|READER_ACTIVE)))
2674 cacheex_left++;
2675#endif
2676 if (((ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED|READER_LOCAL|READER_ACTIVE)) == (REQUEST_SENT|READER_LOCAL|READER_ACTIVE)))
2677 local_left++;
2678 if (((ea_list->status & (REQUEST_ANSWERED|READER_ACTIVE)) == (READER_ACTIVE)))
2679 reader_left++;
2680 }
2681
2682#ifdef CS_CACHEEX
2683 if (has_cacheex && !cacheex_left && !ert->cacheex_done) {
2684 ert->cacheex_done = 1;
2685 request_cw(ert);
2686 } else
2687#endif
2688 if (cfg.preferlocalcards && !local_left && !ert->locals_done) {
2689 ert->locals_done = 1;
2690 request_cw(ert);
2691 }
2692 }
2693
2694 break;
2695 default:
2696 cs_log("unexpected ecm answer rc=%d.", ea->rc);
2697 return;
2698 break;
2699 }
2700
2701 if (ea->rc == E_NOTFOUND && !reader_left) {
2702 // no more matching reader
2703 ert->rc=E_NOTFOUND; //so we set the return code
2704 }
2705
2706#ifdef WITH_LB
2707 send_reader_stat(eardr, ert, ea, ea->rc);
2708#endif
2709
2710#ifdef CS_CACHEEX
2711 if (ea->rc < E_NOTFOUND && !ert->ecmcacheptr)
2712 cs_cache_push(ert);
2713#endif
2714
2715 if (ert->rc < E_99) {
2716 if (cl) send_dcw(cl, ert);
2717 if (!ert->ecmcacheptr)
2718 distribute_ecm(ert, (ert->rc == E_FOUND)?E_CACHE2:ert->rc);
2719 }
2720
2721 return;
2722}
2723
2724uint32_t chk_provid(uchar *ecm, uint16_t caid) {
2725 int32_t i, len, descriptor_length = 0;
2726 uint32_t provid = 0;
2727
2728 switch(caid >> 8) {
2729 case 0x01:
2730 // seca
2731 provid = b2i(2, ecm+3);
2732 break;
2733
2734 case 0x05:
2735 // viaccess
2736 i = (ecm[4] == 0xD2) ? ecm[5]+2 : 0; // skip d2 nano
2737 if((ecm[5+i] == 3) && ((ecm[4+i] == 0x90) || (ecm[4+i] == 0x40)))
2738 provid = (b2i(3, ecm+6+i) & 0xFFFFF0);
2739
2740 i = (ecm[6] == 0xD2) ? ecm[7]+2 : 0; // skip d2 nano long ecm
2741 if((ecm[7+i] == 7) && ((ecm[6+i] == 0x90) || (ecm[6+i] == 0x40)))
2742 provid = (b2i(3, ecm+8+i) & 0xFFFFF0);
2743
2744 break;
2745
2746 case 0x0D:
2747 // cryptoworks
2748 len = (((ecm[1] & 0xf) << 8) | ecm[2])+3;
2749 for(i=8; i<len; i+=descriptor_length+2) {
2750 descriptor_length = ecm[i+1];
2751 if (ecm[i] == 0x83) {
2752 provid = (uint32_t)ecm[i+2] & 0xFE;
2753 break;
2754 }
2755 }
2756 break;
2757
2758#ifdef WITH_LB
2759 default:
2760 for (i=0;i<CS_MAXCAIDTAB;i++) {
2761 uint16_t tcaid = cfg.lb_noproviderforcaid.caid[i];
2762 if (!tcaid) break;
2763 if (tcaid == caid) {
2764 provid = 0;
2765 break;
2766 }
2767 if (tcaid < 0x0100 && (caid >> 8) == tcaid) {
2768 provid = 0;
2769 break;
2770 }
2771 }
2772#endif
2773 }
2774 return(provid);
2775}
2776
2777#ifdef IRDETO_GUESSING
2778void guess_irdeto(ECM_REQUEST *er)
2779{
2780 uchar b3;
2781 int32_t b47;
2782 //uint16_t chid;
2783 struct s_irdeto_quess *ptr;
2784
2785 b3 = er->ecm[3];
2786 ptr = cfg.itab[b3];
2787 if( !ptr ) {
2788 cs_debug_mask(D_TRACE, "unknown irdeto byte 3: %02X", b3);
2789 return;
2790 }
2791 b47 = b2i(4, er->ecm+4);
2792 //chid = b2i(2, er->ecm+6);
2793 //cs_debug_mask(D_TRACE, "ecm: b47=%08X, ptr->b47=%08X, ptr->caid=%04X", b47, ptr->b47, ptr->caid);
2794 while( ptr )
2795 {
2796 if( b47==ptr->b47 )
2797 {
2798 if( er->srvid && (er->srvid!=ptr->sid) )
2799 {
2800 cs_debug_mask(D_TRACE, "sid mismatched (ecm: %04X, guess: %04X), wrong oscam.ird file?",
2801 er->srvid, ptr->sid);
2802 return;
2803 }
2804 er->caid=ptr->caid;
2805 er->srvid=ptr->sid;
2806 er->chid=(uint16_t)ptr->b47;
2807// cs_debug_mask(D_TRACE, "quess_irdeto() found caid=%04X, sid=%04X, chid=%04X",
2808// er->caid, er->srvid, er->chid);
2809 return;
2810 }
2811 ptr=ptr->next;
2812 }
2813}
2814#endif
2815
2816void convert_to_beta(struct s_client *cl, ECM_REQUEST *er, uint16_t caidto)
2817{
2818 static uchar headerN3[10] = {0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12};
2819 static uchar headerN2[10] = {0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12};
2820
2821 er->ocaid = er->caid;
2822 er->caid = caidto;
2823 er->prid = 0;
2824 er->l = er->ecm[2] + 3;
2825
2826 memmove(er->ecm + 13, er->ecm + 3, er->l - 3);
2827
2828 if (er->l > 0x88) {
2829 memcpy(er->ecm + 3, headerN3, 10);
2830
2831 if (er->ecm[0] == 0x81)
2832 er->ecm[12] += 1;
2833
2834 er->ecm[1]=0x70;
2835 }
2836 else
2837 memcpy(er->ecm + 3, headerN2, 10);
2838
2839 er->l += 10;
2840 er->ecm[2] = er->l - 3;
2841 er->btun = 1;
2842
2843 cl->cwtun++;
2844 cl->account->cwtun++;
2845 first_client->cwtun++;
2846
2847 cs_debug_mask(D_TRACE, "ECM converted from: 0x%X to BetaCrypt: 0x%X for service id:0x%X",
2848 er->ocaid, caidto, er->srvid);
2849}
2850
2851
2852void cs_betatunnel(ECM_REQUEST *er)
2853{
2854 int32_t n;
2855 struct s_client *cl = cur_client();
2856 uint32_t mask_all = 0xFFFF;
2857
2858 TUNTAB *ttab;
2859 ttab = &cl->ttab;
2860
2861 if (er->caid>>8 == 0x18)
2862 cs_ddump_mask(D_TRACE, er->ecm, 13, "betatunnel? ecmlen=%d", er->l);
2863
2864 for (n = 0; n<ttab->n; n++) {
2865 if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all)) {
2866
2867 convert_to_beta(cl, er, ttab->bt_caidto[n]);
2868
2869 return;
2870 }
2871 }
2872}
2873
2874static void guess_cardsystem(ECM_REQUEST *er)
2875{
2876 uint16_t last_hope=0;
2877
2878 // viaccess - check by provid-search
2879 if( (er->prid=chk_provid(er->ecm, 0x500)) )
2880 er->caid=0x500;
2881
2882 // nagra
2883 // is ecm[1] always 0x30 ?
2884 // is ecm[3] always 0x07 ?
2885 if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
2886 er->caid=0x1801;
2887
2888 // seca2 - very poor
2889 if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
2890 last_hope=0x100;
2891
2892 // is cryptoworks, but which caid ?
2893 if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
2894 (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
2895 last_hope=0xd00;
2896
2897#ifdef IRDETO_GUESSING
2898 if (!er->caid && er->ecm[2]==0x31 && er->ecm[0x0b]==0x28)
2899 guess_irdeto(er);
2900#endif
2901
2902 if (!er->caid) // guess by len ..
2903 er->caid=len4caid[er->ecm[2]+3];
2904
2905 if (!er->caid)
2906 er->caid=last_hope;
2907}
2908
2909void get_cw(struct s_client * client, ECM_REQUEST *er)
2910{
2911 int32_t i, j, m;
2912 time_t now = time((time_t*)0);
2913 uint32_t line = 0;
2914
2915 er->client = client;
2916 client->lastecm = now;
2917
2918 if (client == first_client || !client ->account || client->account == first_client->account) {
2919 //DVBApi+serial is allowed to request anonymous accounts:
2920 int16_t lt = ph[client->ctyp].listenertype;
2921 if (lt != LIS_DVBAPI && lt != LIS_SERIAL) {
2922 er->rc = E_INVALID;
2923 er->rcEx = E2_GLOBAL;
2924 snprintf(er->msglog, sizeof(er->msglog), "invalid user account %s", username(client));
2925 }
2926 }
2927
2928 if (er->l > MAX_ECM_SIZE) {
2929 er->rc = E_INVALID;
2930 er->rcEx = E2_GLOBAL;
2931 snprintf(er->msglog, sizeof(er->msglog), "ECM size %d > Max Ecm size %d, ignored! client %s", er->l, MAX_ECM_SIZE, username(client));
2932 }
2933
2934 if (!client->grp) {
2935 er->rc = E_INVALID;
2936 er->rcEx = E2_GROUP;
2937 snprintf(er->msglog, sizeof(er->msglog), "invalid user group %s", username(client));
2938 }
2939
2940
2941 if (!er->caid)
2942 guess_cardsystem(er);
2943
2944 /* Quickfix Area */
2945
2946 if( (er->caid & 0xFF00) == 0x600 && !er->chid )
2947 er->chid = (er->ecm[6]<<8)|er->ecm[7];
2948
2949 // quickfix for 0100:000065
2950 if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
2951 er->srvid = 0x0642;
2952
2953 // Quickfixes for Opticum/Globo HD9500
2954 // Quickfix for 0500:030300
2955 if (er->caid == 0x500 && er->prid == 0x030300)
2956 er->prid = 0x030600;
2957
2958 // Quickfix for 0500:D20200
2959 if (er->caid == 0x500 && er->prid == 0xD20200)
2960 er->prid = 0x030600;
2961
2962 //betacrypt ecm with nagra header
2963 if (er->caid == 0x1702 && er->l == 0x89 && er->ecm[3] == 0x07 && er->ecm[4] == 0x84)
2964 er->caid = 0x1833;
2965
2966 //Ariva quickfix (invalid nagra provider)
2967 if (((er->caid & 0xFF00) == 0x1800) && er->prid > 0x00FFFF) er->prid=0;
2968
2969 //Check for invalid provider, extract provider out of ecm:
2970 uint32_t prid = chk_provid(er->ecm, er->caid);
2971 if (!er->prid)
2972 er->prid = prid;
2973 else
2974 {
2975 if (prid && prid != er->prid) {
2976 cs_debug_mask(D_TRACE, "provider fixed: %04X:%06X to %04X:%06X",er->caid, er->prid, er->caid, prid);
2977 er->prid = prid;
2978 }
2979 }
2980
2981 // Set providerid for newcamd clients if none is given
2982 if( (!er->prid) && client->ncd_server ) {
2983 int32_t pi = client->port_idx;
2984 if( pi >= 0 && cfg.ncd_ptab.nports && cfg.ncd_ptab.nports >= pi )
2985 er->prid = cfg.ncd_ptab.ports[pi].ftab.filts[0].prids[0];
2986 }
2987
2988 // ECM nano not supported
2989 if (er->caid == 0x0100 && (er->prid == 0x003311 || er->prid == 0x003315) && er->ecm[5] != 0x00) {
2990 er->rc = E_NOTFOUND;
2991 er->rcEx = E2_WRONG_CHKSUM;
2992 snprintf( er->msglog, MSGLOGSIZE, "ECM nano %02x not supported", er->ecm[5] );
2993 }
2994
2995 // CAID not supported or found
2996 if (!er->caid) {
2997 er->rc = E_INVALID;
2998 er->rcEx = E2_CAID;
2999 snprintf( er->msglog, MSGLOGSIZE, "CAID not supported or found" );
3000 }
3001
3002 // user expired
3003 if(client->expirationdate && client->expirationdate < client->lastecm)
3004 er->rc = E_EXPDATE;
3005
3006 // out of timeframe
3007 if(client->allowedtimeframe[0] && client->allowedtimeframe[1]) {
3008 struct tm acttm;
3009 localtime_r(&now, &acttm);
3010 int32_t curtime = (acttm.tm_hour * 60) + acttm.tm_min;
3011 int32_t mintime = client->allowedtimeframe[0];
3012 int32_t maxtime = client->allowedtimeframe[1];
3013 if(!((mintime <= maxtime && curtime > mintime && curtime < maxtime) || (mintime > maxtime && (curtime > mintime || curtime < maxtime)))) {
3014 er->rc = E_EXPDATE;
3015 }
3016 cs_debug_mask(D_TRACE, "Check Timeframe - result: %d, start: %d, current: %d, end: %d\n",er->rc, mintime, curtime, maxtime);
3017 }
3018
3019 // user disabled
3020 if(client->disabled != 0) {
3021 if (client->failban & BAN_DISABLED){
3022 cs_add_violation(client, client->account->usr);
3023 cs_disconnect_client(client);
3024 }
3025 er->rc = E_DISABLED;
3026 }
3027
3028 if (!chk_global_whitelist(er, &line)) {
3029 cs_debug_mask(D_TRACE, "whitelist filtered: %s (%04X&%06X/%04X/%04X/%02X:%04X) line %d",
3030 username(client), er->caid, er->prid, er->pid, er->srvid, er->l, htons(er->checksum),
3031 line);
3032 er->rc = E_INVALID;
3033 }
3034
3035 // rc<100 -> ecm error
3036 if (er->rc >= E_UNHANDLED) {
3037 m = er->caid;
3038 i = er->srvid;
3039
3040 if ((i != client->last_srvid) || (!client->lastswitch)) {
3041 if(cfg.usrfileflag)
3042 cs_statistics(client);
3043 client->lastswitch = now;
3044 }
3045
3046 // user sleeping
3047 if ((client->tosleep) && (now - client->lastswitch > client->tosleep)) {
3048
3049 if (client->failban & BAN_SLEEPING) {
3050 cs_add_violation(client, client->account->usr);
3051 cs_disconnect_client(client);
3052 }
3053
3054 if (client->c35_sleepsend != 0) {
3055 er->rc = E_STOPPED; // send stop command CMD08 {00 xx}
3056 } else {
3057 er->rc = E_SLEEPING;
3058 }
3059 }
3060
3061 client->last_srvid = i;
3062 client->last_caid = m;
3063
3064 int32_t ecm_len = (((er->ecm[1] & 0x0F) << 8) | er->ecm[2]) + 3;
3065
3066 for (j = 0; (j < 6) && (er->rc >= E_UNHANDLED); j++)
3067 {
3068 switch(j) {
3069
3070 case 0:
3071 // fake (uniq)
3072 if (client->dup)
3073 er->rc = E_FAKE;
3074 break;
3075
3076 case 1:
3077 // invalid (caid)
3078 if (!chk_bcaid(er, &client->ctab)) {
3079 er->rc = E_INVALID;
3080 er->rcEx = E2_CAID;
3081 snprintf( er->msglog, MSGLOGSIZE, "invalid caid %x",er->caid );
3082 }
3083 break;
3084
3085 case 2:
3086 // invalid (srvid)
3087 if (!chk_srvid(client, er))
3088 {
3089 er->rc = E_INVALID;
3090 snprintf( er->msglog, MSGLOGSIZE, "invalid SID" );
3091 }
3092
3093 break;
3094
3095 case 3:
3096 // invalid (ufilters)
3097 if (!chk_ufilters(er))
3098 er->rc = E_INVALID;
3099 break;
3100
3101 case 4:
3102 // invalid (sfilter)
3103 if (!chk_sfilter(er, ph[client->ctyp].ptab))
3104 er->rc = E_INVALID;
3105 break;
3106
3107 case 5:
3108 // corrupt
3109 if( (i = er->l - ecm_len) ) {
3110 if (i > 0) {
3111 cs_debug_mask(D_TRACE, "warning: ecm size adjusted from 0x%X to 0x%X", er->l, ecm_len);
3112 er->l = ecm_len;
3113 }
3114 else
3115 er->rc = E_CORRUPT;
3116 }
3117 break;
3118 }
3119 }
3120 }
3121
3122 //Schlocke: above checks could change er->rc so
3123 if (er->rc >= E_UNHANDLED) {
3124 /*BetaCrypt tunneling
3125 *moved behind the check routines,
3126 *because newcamd ECM will fail
3127 *if ECM is converted before
3128 */
3129 if (client->ttab.n)
3130 cs_betatunnel(er);
3131
3132 // ignore ecm ...
3133 int32_t offset = 3;
3134 // ... and betacrypt header for cache md5 calculation
3135 if ((er->caid >> 8) == 0x17)
3136 offset = 13;
3137 unsigned char md5tmp[MD5_DIGEST_LENGTH];
3138 // store ECM in cache
3139 memcpy(er->ecmd5, MD5(er->ecm+offset, er->l-offset, md5tmp), CS_ECMSTORESIZE);
3140#ifdef CS_CACHEEX
3141 er->csp_hash = csp_ecm_hash(er);
3142#endif
3143
3144#ifdef CS_ANTICASC
3145 ac_chk(client, er, 0);
3146#endif
3147 }
3148
3149 struct s_ecm_answer *ea, *prv = NULL;
3150#ifdef CS_CACHEEX
3151 if(er->rc >= E_99 && !is_match_alias(client, er)) {
3152#else
3153 if(er->rc >= E_99) {
3154#endif
3155 er->reader_avail=0;
3156 struct s_reader *rdr;
3157
3158 for (rdr=first_active_reader; rdr ; rdr=rdr->next) {
3159 int8_t match = matching_reader(er, rdr);
3160#ifdef WITH_LB
3161 //if this reader does not match, check betatunnel for it
3162 if (!match && cfg.lb_auto_betatunnel) {
3163 uint16_t caid = get_betatunnel_caid_to(er->caid);
3164 if (caid) {
3165 uint16_t save_caid = er->caid;
3166 er->caid = caid;
3167 match = matching_reader(er, rdr); //matching
3168 er->caid = save_caid;
3169 }
3170 }
3171#endif
3172 if (match) {
3173 cs_malloc(&ea, sizeof(struct s_ecm_answer), 0);
3174 ea->reader = rdr;
3175 if (prv)
3176 prv->next = ea;
3177 else
3178 er->matching_rdr=ea;
3179
3180 prv = ea;
3181
3182 ea->status = READER_ACTIVE;
3183 if (!(rdr->typ & R_IS_NETWORK))
3184 ea->status |= READER_LOCAL;
3185#ifdef CS_CACHEEX
3186 else if (rdr->cacheex == 1)
3187 ea->status |= READER_CACHEEX;
3188#endif
3189 else if (rdr->fallback)
3190 ea->status |= READER_FALLBACK;
3191
3192#ifdef WITH_LB
3193 if (cfg.lb_mode || !rdr->fallback)
3194#else
3195 if (!rdr->fallback)
3196#endif
3197 er->reader_avail++;
3198 }
3199 }
3200
3201#ifdef WITH_LB
3202 if (cfg.lb_mode && er->reader_avail) {
3203 cs_debug_mask(D_TRACE, "requesting client %s best reader for %04X/%06X/%04X/%04X",
3204 username(client), er->caid, er->prid, er->pid, er->srvid);
3205 get_best_reader(er);
3206 }
3207#endif
3208
3209 int32_t fallback_reader_count = 0;
3210 er->reader_count = 0;
3211 for (ea = er->matching_rdr; ea; ea = ea->next) {
3212 if (ea->status & READER_ACTIVE) {
3213 if (!(ea->status & READER_FALLBACK))
3214 er->reader_count++;
3215 else
3216 fallback_reader_count++;
3217 }
3218 }
3219
3220 if ((er->reader_count + fallback_reader_count) == 0) { //no reader -> not found
3221 er->rc = E_NOTFOUND;
3222 if (!er->rcEx)
3223 er->rcEx = E2_GROUP;
3224 snprintf(er->msglog, MSGLOGSIZE, "no matching reader");
3225 }
3226 }
3227
3228 //we have to go through matching_reader() to check services!
3229 struct ecm_request_t *ecm;
3230 if (er->rc == E_UNHANDLED) {
3231 ecm = check_cwcache(er, client);
3232
3233 if (ecm) {
3234 if (ecm->rc < E_99) {
3235 memcpy(er->cw, ecm->cw, 16);
3236 er->selected_reader = ecm->selected_reader;
3237 er->rc = (ecm->rc == E_FOUND)?E_CACHE1:ecm->rc;
3238 } else { //E_UNHANDLED
3239 er->ecmcacheptr = ecm;
3240 er->rc = E_99;
3241#ifdef CS_CACHEEX
3242 //to support cache without ecms we store the first client ecm request here
3243 //when we go a cache ecm from cacheex
3244 if (!ecm->l && er->l && !ecm->matching_rdr) {
3245 ecm->matching_rdr = er->matching_rdr;
3246 er->matching_rdr = NULL;
3247 ecm->l = er->l;
3248 ecm->client = er->client;
3249 ecm->checksum = er->checksum;
3250 er->client = NULL;
3251 memcpy(ecm->ecm, er->ecm, sizeof(ecm->ecm));
3252 memcpy(ecm->ecmd5, er->ecmd5, sizeof(ecm->ecmd5));
3253 }
3254#endif
3255 }
3256#ifdef CS_CACHEEX
3257 er->cacheex_src = ecm->cacheex_src;
3258#endif
3259 } else
3260 er->rc = E_UNHANDLED;
3261 }
3262
3263#ifdef CS_CACHEEX
3264 int8_t cacheex = client->account?client->account->cacheex:0;
3265
3266 if ((cacheex == 1 || cfg.csp_wait_time) && er->rc == E_UNHANDLED) { //not found in cache, so wait!
3267 uint32_t max_wait = (cacheex == 1)?cfg.cacheex_wait_time:cfg.csp_wait_time;
3268 while (max_wait > 0 && !client->kill) {
3269 cs_sleepms(50);
3270 max_wait -= 50;
3271 ecm = check_cwcache(er, client);
3272 if (ecm) {
3273 if (ecm->rc < E_99) { //Found cache!
3274 memcpy(er->cw, ecm->cw, 16);
3275 er->selected_reader = ecm->selected_reader;
3276 er->rc = (ecm->rc == E_FOUND)?E_CACHE1:ecm->rc;
3277 } else { //Found request!
3278 er->ecmcacheptr = ecm;
3279 er->rc = E_99;
3280 }
3281 er->cacheex_src = ecm->cacheex_src;
3282 break;
3283 }
3284 }
3285 }
3286#endif
3287
3288 if (er->rc >= E_99) {
3289#ifdef CS_CACHEEX
3290 if (cacheex == 0 || er->rc == E_99) { //Cacheex should not add to the ecmcache:
3291#endif
3292 cs_writelock(&ecmcache_lock);
3293 er->next = ecmcwcache;
3294 ecmcwcache = er;
3295 ecmcwcache_size++;
3296 cs_writeunlock(&ecmcache_lock);
3297
3298 if (er->rc == E_UNHANDLED) {
3299 ecm = check_cwcache(er, client);
3300 if (ecm && ecm != er) {
3301 er->rc = E_99;
3302 er->ecmcacheptr = ecm;
3303#ifdef CS_CACHEEX
3304 er->cacheex_src = ecm->cacheex_src;
3305#endif
3306 }
3307 }
3308#ifdef CS_CACHEEX
3309 }
3310#endif
3311 }
3312
3313 uint16_t *lp;
3314 for (lp=(uint16_t *)er->ecm+(er->l>>2), er->checksum=0; lp>=(uint16_t *)er->ecm; lp--)
3315 er->checksum^=*lp;
3316
3317 if (er->rc < E_99) {
3318#ifdef CS_CACHEEX
3319 if (cfg.delay && cacheex == 0) //No delay on cacheexchange!
3320 cs_sleepms(cfg.delay);
3321
3322 if (cacheex == 1 && er->rc < E_NOTFOUND) {
3323 cs_add_cacheex_stats(client, er->caid, er->srvid, er->prid, 0);
3324 client->cwcacheexpush++;
3325 if (client->account)
3326 client->account->cwcacheexpush++;
3327 first_client->cwcacheexpush++;
3328 }
3329#else
3330 if (cfg.delay)
3331 cs_sleepms(cfg.delay);
3332#endif
3333 send_dcw(client, er);
3334 free_ecm(er);
3335 return; //ECM found/not found/error/invalid
3336 }
3337
3338 if (er->rc == E_99) {
3339 er->stage=4;
3340 if(timecheck_client){
3341 pthread_mutex_lock(&timecheck_client->thread_lock);
3342 if(timecheck_client->thread_active == 2)
3343 pthread_kill(timecheck_client->thread, OSCAM_SIGNAL_WAKEUP);
3344 pthread_mutex_unlock(&timecheck_client->thread_lock);
3345 }
3346 return; //ECM already requested / found in ECM cache
3347 }
3348
3349#ifdef CS_CACHEEX
3350 //er->rc == E_UNHANDLED
3351 //Cache Exchange never request cws from readers!
3352 if (cacheex == 1) {
3353 er->rc = E_NOTFOUND;
3354 er->rcEx = E2_OFFLINE;
3355 send_dcw(client, er);
3356 free_ecm(er);
3357 return;
3358 }
3359#endif
3360
3361 er->rcEx = 0;
3362 request_cw(er);
3363
3364 cs_ddump_mask(D_CLIENTECM, er->ecm, er->l, "Client %s ECM dump %04X:%06X:%04X:%04X", username(client),
3365 er->caid, er->prid, er->srvid, er->l);
3366
3367 if(timecheck_client){
3368 pthread_mutex_lock(&timecheck_client->thread_lock);
3369 if(timecheck_client->thread_active == 2)
3370 pthread_kill(timecheck_client->thread, OSCAM_SIGNAL_WAKEUP);
3371 pthread_mutex_unlock(&timecheck_client->thread_lock);
3372 }
3373}
3374
3375void do_emm(struct s_client * client, EMM_PACKET *ep)
3376{
3377 char *typtext[]={"unknown", "unique", "shared", "global"};
3378 char tmp[17];
3379
3380 struct s_reader *aureader = NULL;
3381 cs_ddump_mask(D_EMM, ep->emm, ep->l, "emm:");
3382
3383 LL_ITER itr = ll_iter_create(client->aureader_list);
3384 while ((aureader = ll_iter_next(&itr))) {
3385 if (!aureader->enable)
3386 continue;
3387
3388 uint16_t caid = b2i(2, ep->caid);
3389 uint32_t provid = b2i(4, ep->provid);
3390
3391 if (aureader->audisabled) {
3392 cs_debug_mask(D_EMM, "AU is disabled for reader %s", aureader->label);
3393 /* we have to write the log for blocked EMM here because
3394 this EMM never reach the reader module where the rest
3395 of EMM log is done. */
3396 if (aureader->logemm & 0x10) {
3397 cs_log("%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms) by %s",
3398 client->account->usr,
3399 typtext[ep->type],
3400 ep->emm[2],
3401 aureader->label);
3402 }
3403 continue;
3404 }
3405
3406 if (!(aureader->grp & client->grp)) {
3407 cs_debug_mask(D_EMM, "skip emm reader %s group mismatch", aureader->label);
3408 continue;
3409 }
3410
3411 //TODO: provider possibly not set yet, this is done in get_emm_type()
3412 if (!emm_reader_match(aureader, caid, provid))
3413 continue;
3414
3415 struct s_cardsystem *cs = NULL;
3416
3417 if (aureader->typ & R_IS_CASCADING) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM)
3418 if (!aureader->ph.c_send_emm) // no emm support
3419 continue;
3420
3421 cs = get_cardsystem_by_caid(caid);
3422 if (!cs) {
3423 cs_debug_mask(D_EMM, "unable to find cardsystem for caid %04X, reader %s", caid, aureader->label);
3424 continue;
3425 }
3426 } else { // local reader
3427 if (aureader->csystem.active)
3428 cs=&aureader->csystem;
3429 }
3430
3431 if (cs && cs->get_emm_type) {
3432 if(!cs->get_emm_type(ep, aureader)) {
3433 cs_debug_mask(D_EMM, "emm skipped, get_emm_type() returns error, reader %s", aureader->label);
3434 client->emmnok++;
3435 if (client->account)
3436 client->account->emmnok++;
3437 first_client->emmnok++;
3438 continue;
3439 }
3440 }
3441
3442 cs_debug_mask(D_EMM, "emmtype %s. Reader %s has serial %s.", typtext[ep->type], aureader->label, cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp)));
3443 cs_ddump_mask(D_EMM, ep->hexserial, 8, "emm UA/SA:");
3444
3445 uint32_t emmtype;
3446 if (ep->type == UNKNOWN)
3447 emmtype = EMM_UNKNOWN;
3448 else
3449 emmtype = 1 << (ep->type-1);
3450 client->last=time((time_t*)0);
3451 if (((1<<(ep->emm[0] % 0x80)) & aureader->s_nano) || (aureader->saveemm & emmtype)) { //should this nano be saved?
3452 char token[256];
3453 char *tmp2;
3454 FILE *fp;
3455 time_t rawtime;
3456 time (&rawtime);
3457 struct tm timeinfo;
3458 localtime_r (&rawtime, &timeinfo); /* to access LOCAL date/time info */
3459 int32_t emm_length = ((ep->emm[1] & 0x0f) << 8) | ep->emm[2];
3460 char buf[80];
3461 strftime (buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", &timeinfo);
3462 snprintf (token, sizeof(token), "%s%s_emm.log", cfg.emmlogdir?cfg.emmlogdir:cs_confdir, aureader->label);
3463
3464 if (!(fp = fopen (token, "a"))) {
3465 cs_log ("ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
3466 } else if(cs_malloc(&tmp2, (emm_length + 3)*2 + 1, -1)){
3467 fprintf (fp, "%s %s ", buf, cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp)));
3468 fprintf (fp, "%s\n", cs_hexdump(0, ep->emm, emm_length + 3, tmp2, (emm_length + 3)*2 + 1));
3469 free(tmp2);
3470 fclose (fp);
3471 cs_log ("Successfully added EMM to %s.", token);
3472 }
3473
3474 snprintf (token, sizeof(token), "%s%s_emm.bin", cfg.emmlogdir?cfg.emmlogdir:cs_confdir, aureader->label);
3475 if (!(fp = fopen (token, "ab"))) {
3476 cs_log ("ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
3477 } else {
3478 if ((int)fwrite(ep->emm, 1, emm_length+3, fp) == emm_length+3) {
3479 cs_log ("Successfully added binary EMM to %s.", token);
3480 } else {
3481 cs_log ("ERROR: Cannot write binary EMM to %s (errno=%d: %s)\n", token, errno, strerror(errno));
3482 }
3483 fclose (fp);
3484 }
3485 }
3486
3487 int32_t is_blocked = 0;
3488 switch (ep->type) {
3489 case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) ? 1 : 0;
3490 break;
3491 case UNIQUE: is_blocked = (aureader->blockemm & EMM_UNIQUE) ? 1 : 0;
3492 break;
3493 case SHARED: is_blocked = (aureader->blockemm & EMM_SHARED) ? 1 : 0;
3494 break;
3495 case GLOBAL: is_blocked = (aureader->blockemm & EMM_GLOBAL) ? 1 : 0;
3496 break;
3497 }
3498
3499 // if not already blocked we check for block by len
3500 if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ;
3501
3502 if (is_blocked != 0) {
3503#ifdef WEBIF
3504 aureader->emmblocked[ep->type]++;
3505 is_blocked = aureader->emmblocked[ep->type];
3506#endif
3507 /* we have to write the log for blocked EMM here because
3508 this EMM never reach the reader module where the rest
3509 of EMM log is done. */
3510 if (aureader->logemm & 0x08) {
3511 cs_log("%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms) by %s",
3512 client->account->usr,
3513 typtext[ep->type],
3514 ep->emm[2],
3515 is_blocked,
3516 aureader->label);
3517 }
3518 continue;
3519 }
3520
3521 client->lastemm = time((time_t*)0);
3522
3523 client->emmok++;
3524 if (client->account)
3525 client->account->emmok++;
3526 first_client->emmok++;
3527
3528 //Check emmcache early:
3529 int32_t i;
3530 unsigned char md5tmp[CS_EMMSTORESIZE];
3531 struct s_client *au_cl = aureader->client;
3532
3533 MD5(ep->emm, ep->emm[2], md5tmp);
3534 ep->client = client;
3535
3536 for (i=0; i<CS_EMMCACHESIZE; i++) {
3537 if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) {
3538 au_cl->emmcache[i].count++;
3539 cs_debug_mask(D_EMM, "emm found in cache: reader %s count %d rewrite %d", aureader->label, au_cl->emmcache[i].count, aureader->rewritemm);
3540 if (aureader->cachemm && (au_cl->emmcache[i].count < aureader->rewritemm)) {
3541 reader_log_emm(aureader, ep, i, 2, NULL);
3542 return;
3543 }
3544 }
3545 }
3546
3547 cs_debug_mask(D_EMM, "emm is being sent to reader %s.", aureader->label);
3548
3549 EMM_PACKET *emm_pack = cs_malloc(&emm_pack, sizeof(EMM_PACKET), -1);
3550 memcpy(emm_pack, ep, sizeof(EMM_PACKET));
3551 add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET));
3552 }
3553}
3554
3555int32_t process_input(uchar *buf, int32_t l, int32_t timeout)
3556{
3557 int32_t rc, i, pfdcount;
3558 struct pollfd pfd[2];
3559 struct s_client *cl = cur_client();
3560
3561 time_t starttime = time(NULL);
3562
3563 while (1) {
3564 pfdcount = 0;
3565 if (cl->pfd) {
3566 pfd[pfdcount].fd = cl->pfd;
3567 pfd[pfdcount++].events = POLLIN | POLLPRI;
3568 }
3569
3570 int32_t p_rc = poll(pfd, pfdcount, 0);
3571
3572 if (p_rc < 0) {
3573 if (errno==EINTR) continue;
3574 else return(0);
3575 }
3576
3577 if (p_rc == 0 && (starttime+timeout) < time(NULL)) { // client maxidle reached
3578 rc=(-9);
3579 break;
3580 }
3581
3582 for (i=0;i<pfdcount && p_rc > 0;i++) {
3583 if (pfd[i].revents & POLLHUP){ // POLLHUP is only valid in revents so it doesn't need to be set above in events
3584 return(0);
3585 }
3586 if (!(pfd[i].revents & (POLLIN | POLLPRI)))
3587 continue;
3588
3589 if (pfd[i].fd == cl->pfd)
3590 return ph[cl->ctyp].recv(cl, buf, l);
3591 }
3592 }
3593 return(rc);
3594}
3595
3596void cs_waitforcardinit()
3597{
3598 if (cfg.waitforcards)
3599 {
3600 cs_log("waiting for local card init");
3601 int32_t card_init_done;
3602 do {
3603 card_init_done = 1;
3604 struct s_reader *rdr;
3605 LL_ITER itr = ll_iter_create(configured_readers);
3606 while((rdr = ll_iter_next(&itr))) {
3607 if (rdr->enable && (!(rdr->typ & R_IS_CASCADING)) && (rdr->card_status == CARD_NEED_INIT || rdr->card_status == UNKNOWN)) {
3608 card_init_done = 0;
3609 break;
3610 }
3611 }
3612
3613 if (!card_init_done)
3614 cs_sleepms(300); // wait a little bit
3615 //alarm(cfg.cmaxidle + cfg.ctimeout / 1000 + 1);
3616 } while (!card_init_done);
3617 if (cfg.waitforcards_extra_delay>0)
3618 cs_sleepms(cfg.waitforcards_extra_delay);
3619 cs_log("init for all local cards done");
3620 }
3621}
3622
3623static void check_status(struct s_client *cl) {
3624 if (!cl || cl->kill || !cl->init_done)
3625 return;
3626
3627 struct s_reader *rdr = cl->reader;
3628
3629 switch (cl->typ) {
3630 case 'm':
3631 case 'c':
3632 //check clients for exceeding cmaxidle by checking cl->last
3633 if (!(cl->ncd_keepalive && (ph[cl->ctyp].listenertype & LIS_NEWCAMD)) && cl->last && cfg.cmaxidle && (time(NULL) - cl->last) > (time_t)cfg.cmaxidle) {
3634 add_job(cl, ACTION_CLIENT_IDLE, NULL, 0);
3635 }
3636
3637 break;
3638#ifdef WITH_CARDREADER
3639 case 'r':
3640 //check for card inserted or card removed on pysical reader
3641 if (!rdr || !rdr->enable)
3642 break;
3643 add_job(cl, ACTION_READER_CHECK_HEALTH, NULL, 0);
3644 break;
3645#endif
3646 case 'p':
3647 //execute reader do idle on proxy reader after a certain time (rdr->tcp_ito = inactivitytimeout)
3648 //disconnect when no keepalive available
3649 if (!rdr || !rdr->enable)
3650 break;
3651 if (rdr->tcp_ito && (rdr->typ & R_IS_CASCADING)) {
3652 int32_t time_diff;
3653 time_diff = abs(time(NULL) - rdr->last_check);
3654
3655 if (time_diff>60) { //check 1x per minute
3656 add_job(rdr->client, ACTION_READER_IDLE, NULL, 0);
3657 rdr->last_check = time(NULL);
3658 }
3659 }
3660 if (((time(NULL) - rdr->last_check) > 30) && rdr->typ == R_CCCAM) {
3661 add_job(rdr->client, ACTION_READER_IDLE, NULL, 0);
3662 rdr->last_check = time(NULL);
3663 }
3664 break;
3665 default:
3666 break;
3667 }
3668}
3669
3670void * work_thread(void *ptr) {
3671 struct s_data *data = (struct s_data *) ptr;
3672 struct s_client *cl = data->cl;
3673 struct s_reader *reader = cl->reader;
3674
3675 struct s_data tmp_data;
3676 struct pollfd pfd[1];
3677
3678 pthread_setspecific(getclient, cl);
3679 cl->thread=pthread_self();
3680
3681 uint16_t bufsize = cl?ph[cl->ctyp].bufsize:1024; //CCCam needs more than 1024bytes!
3682 if (!bufsize) bufsize = 1024;
3683 uchar *mbuf = cs_malloc(&mbuf, bufsize, 0);
3684 int32_t n=0, rc=0, i, idx, s;
3685 uchar dcw[16];
3686 time_t now;
3687 int8_t restart_reader=0;
3688
3689 while (1) {
3690// if (!cl || !is_valid_client(cl)) { // corsair: I think this is not necessary anymore and causes memleaks
3691// if (data && data!=&tmp_data)
3692// free(data);
3693// data = NULL;
3694// free(mbuf);
3695// pthread_exit(NULL);
3696// return NULL;
3697// }
3698
3699 if (cl->kill && ll_count(cl->joblist) == 0) { //we need to process joblist to free data->ptr
3700 cs_debug_mask(D_TRACE, "ending thread");
3701 if (data && data!=&tmp_data)
3702 free(data);
3703
3704 data = NULL;
3705 cleanup_thread(cl);
3706 if (restart_reader)
3707 restart_cardreader(reader, 0);
3708 free(mbuf);
3709 pthread_exit(NULL);
3710 return NULL;
3711 }
3712
3713 if (data)
3714 cs_debug_mask(D_TRACE, "data from add_job action=%d client %c %s", data->action, cl->typ, username(cl));
3715
3716 if (!data) {
3717 if(cl->typ != 'r') check_status(cl); // do not call for physical readers as this might cause an endless job loop
3718 pthread_mutex_lock(&cl->thread_lock);
3719 if (cl->joblist && ll_count(cl->joblist)>0) {
3720 LL_ITER itr = ll_iter_create(cl->joblist);
3721 data = ll_iter_next_remove(&itr);
3722 //cs_debug_mask(D_TRACE, "start next job from list action=%d", data->action);
3723 }
3724 pthread_mutex_unlock(&cl->thread_lock);
3725 }
3726
3727 if (!data) {
3728 if (!cl->pfd)
3729 break;
3730 pfd[0].fd = cl->pfd;
3731 pfd[0].events = POLLIN | POLLPRI | POLLHUP;
3732
3733 pthread_mutex_lock(&cl->thread_lock);
3734 cl->thread_active = 2;
3735 pthread_mutex_unlock(&cl->thread_lock);
3736 rc = poll(pfd, 1, 3000);
3737 pthread_mutex_lock(&cl->thread_lock);
3738 cl->thread_active = 1;
3739 pthread_mutex_unlock(&cl->thread_lock);
3740
3741 if (rc == -1)
3742 cs_debug_mask(D_TRACE, "poll wakeup");
3743
3744 if (rc>0) {
3745 cs_debug_mask(D_TRACE, "data on socket");
3746 data=&tmp_data;
3747 data->ptr = NULL;
3748
3749 if (reader)
3750 data->action = ACTION_READER_REMOTE;
3751 else {
3752 if (cl->is_udp) {
3753 data->action = ACTION_CLIENT_UDP;
3754 data->ptr = mbuf;
3755 data->len = bufsize;
3756 }
3757 else
3758 data->action = ACTION_CLIENT_TCP;
3759 if (pfd[0].revents & (POLLHUP | POLLNVAL))
3760 cl->kill = 1;
3761 }
3762 }
3763 }
3764
3765 if (!data)
3766 continue;
3767
3768 if (data->action < 20 && !reader) {
3769 if (data!=&tmp_data)
3770 free(data);
3771 data = NULL;
3772 break;
3773 }
3774
3775 if (!data->action)
3776 break;
3777
3778 now = time(NULL);
3779 time_t diff = (time_t)(cfg.ctimeout/1000)+1;
3780 if (data != &tmp_data && data->time < now-diff) {
3781 cs_log("dropping client data for %s time %ds", username(cl), (int32_t)(now-data->time));
3782 free(data);
3783 data = NULL;
3784 continue;
3785 }
3786
3787 switch(data->action) {
3788 case ACTION_READER_IDLE:
3789 reader_do_idle(reader);
3790 break;
3791 case ACTION_READER_REMOTE:
3792 s = check_fd_for_data(cl->pfd);
3793
3794 if (s == 0) // no data, another thread already read from fd?
3795 break;
3796
3797 if (s < 0) {
3798 if (reader->ph.type==MOD_CONN_TCP)
3799 network_tcp_connection_close(reader, "disconnect");
3800 break;
3801 }
3802
3803 rc = reader->ph.recv(cl, mbuf, bufsize);
3804 if (rc < 0) {
3805 if (reader->ph.type==MOD_CONN_TCP)
3806 network_tcp_connection_close(reader, "disconnect on receive");
3807 break;
3808 }
3809
3810 cl->last=now;
3811 idx=reader->ph.c_recv_chk(cl, dcw, &rc, mbuf, rc);
3812
3813 if (idx<0) break; // no dcw received
3814 if (!idx) idx=cl->last_idx;
3815
3816 reader->last_g=now; // for reconnect timeout
3817
3818 for (i=0, n=0; i<CS_MAXPENDING && n == 0; i++) {
3819 if (cl->ecmtask[i].idx==idx) {
3820 cl->pending--;
3821 casc_check_dcw(reader, i, rc, dcw);
3822 n++;
3823 }
3824 }
3825 break;
3826 case ACTION_READER_REMOTELOG:
3827 casc_do_sock_log(reader);
3828 break;
3829#ifdef WITH_CARDREADER
3830 case ACTION_READER_RESET:
3831 reader_reset(reader);
3832 break;
3833#endif
3834 case ACTION_READER_ECM_REQUEST:
3835 reader_get_ecm(reader, data->ptr);
3836 break;
3837 case ACTION_READER_EMM:
3838 reader_do_emm(reader, data->ptr);
3839 free(data->ptr); // allocated in do_emm()
3840 break;
3841 case ACTION_READER_CARDINFO:
3842 reader_do_card_info(reader);
3843 break;
3844 case ACTION_READER_INIT:
3845 if (!cl->init_done)
3846 reader_init(reader);
3847 break;
3848 case ACTION_READER_RESTART:
3849 cl->kill = 1;
3850 restart_reader = 1;
3851 break;
3852#ifdef WITH_CARDREADER
3853 case ACTION_READER_RESET_FAST:
3854 reader->card_status = CARD_NEED_INIT;
3855 reader_reset(reader);
3856 break;
3857 case ACTION_READER_CHECK_HEALTH:
3858 reader_checkhealth(reader);
3859 break;
3860#endif
3861 case ACTION_CLIENT_UDP:
3862 n = ph[cl->ctyp].recv(cl, data->ptr, data->len);
3863 if (n<0) {
3864 if (data->ptr != mbuf)
3865 free(data->ptr);
3866 break;
3867 }
3868 ph[cl->ctyp].s_handler(cl, data->ptr, n);
3869 if (data->ptr != mbuf)
3870 free(data->ptr); // allocated in accept_connection()
3871 break;
3872 case ACTION_CLIENT_TCP:
3873 s = check_fd_for_data(cl->pfd);
3874 if (s == 0) // no data, another thread already read from fd?
3875 break;
3876 if (s < 0) { // system error or fd wants to be closed
3877 cl->kill=1; // kill client on next run
3878 continue;
3879 }
3880
3881 n = ph[cl->ctyp].recv(cl, mbuf, bufsize);
3882 if (n < 0) {
3883 cl->kill=1; // kill client on next run
3884 continue;
3885 }
3886 ph[cl->ctyp].s_handler(cl, mbuf, n);
3887
3888 break;
3889 case ACTION_CLIENT_ECM_ANSWER:
3890 chk_dcw(cl, data->ptr);
3891 free(data->ptr);
3892 break;
3893 case ACTION_CLIENT_INIT:
3894 if (ph[cl->ctyp].s_init)
3895 ph[cl->ctyp].s_init(cl);
3896 cl->init_done=1;
3897 break;
3898 case ACTION_CLIENT_IDLE:
3899 if (ph[cl->ctyp].s_idle)
3900 ph[cl->ctyp].s_idle(cl);
3901 else {
3902 cs_log("user %s reached %d sec idle limit.", username(cl), cfg.cmaxidle);
3903 cl->kill = 1;
3904 }
3905 break;
3906#ifdef CS_CACHEEX
3907 case ACTION_CACHE_PUSH_OUT: {
3908 ECM_REQUEST *er = data->ptr;
3909
3910 int32_t res=0, stats = -1;
3911 if (reader) {
3912 struct s_client *cl = reader->client;
3913 if(cl){
3914 res = reader->ph.c_cache_push(cl, er);
3915 stats = cs_add_cacheex_stats(cl, er->caid, er->srvid, er->prid, 0);
3916 }
3917 }
3918 else
3919 res = ph[cl->ctyp].c_cache_push(cl, er);
3920
3921
3922 cs_debug_mask(
3923 D_CACHEEX,
3924 "pushed ECM %04X&%06X/%04X/%04X/%02X:%04X to %s res %d stats %d", er->caid, er->prid, er->pid, er->srvid, er->l,
3925 htons(er->checksum), username(cl), res, stats);
3926 free(data->ptr);
3927
3928 cl->cwcacheexpush++;
3929 if (cl->account)
3930 cl->account->cwcacheexpush++;
3931 first_client->cwcacheexpush++;
3932
3933 break;
3934 }
3935#endif
3936 case ACTION_CLIENT_KILL:
3937 cl->kill = 1;
3938 break;
3939 }
3940
3941 if (data!=&tmp_data)
3942 free(data);
3943
3944 data = NULL;
3945 }
3946
3947 if (thread_pipe[1]){
3948 if(write(thread_pipe[1], mbuf, 1) == -1){ //wakeup client check
3949 cs_debug_mask(D_TRACE, "Writing to pipe failed (errno=%d %s)", errno, strerror(errno));
3950 }
3951 }
3952
3953 cs_debug_mask(D_TRACE, "ending thread");
3954 cl->thread_active = 0;
3955 free(mbuf);
3956 pthread_exit(NULL);
3957 return NULL;
3958}
3959
3960void add_job(struct s_client *cl, int8_t action, void *ptr, int32_t len) {
3961
3962 if (!cl) {
3963 cs_log("WARNING: add_job failed.");
3964 if (len && ptr) free(ptr);
3965 return;
3966 }
3967
3968 struct s_data *data = cs_malloc(&data, sizeof(struct s_data), -1);
3969 if (!data && len && ptr) {
3970 free(ptr);
3971 return;
3972 }
3973
3974 data->action = action;
3975 data->ptr = ptr;
3976 data->cl = cl;
3977 data->len = len;
3978 data->time = time(NULL);
3979
3980 pthread_mutex_lock(&cl->thread_lock);
3981 if (cl->thread_active) {
3982 if (!cl->joblist)
3983 cl->joblist = ll_create("joblist");
3984
3985 ll_append(cl->joblist, data);
3986 if(cl->thread_active == 2)
3987 pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP);
3988 pthread_mutex_unlock(&cl->thread_lock);
3989 cs_debug_mask(D_TRACE, "add %s job action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action);
3990 return;
3991 }
3992
3993
3994 pthread_attr_t attr;
3995 pthread_attr_init(&attr);
3996#if !defined(TUXBOX)
3997 /* pcsc doesn't like this either; segfaults on x86, x86_64 */
3998 struct s_reader *rdr = cl->reader;
3999 if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC)
4000 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
4001#endif
4002
4003 cs_debug_mask(D_TRACE, "start %s thread action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action);
4004
4005 int32_t ret = pthread_create(&cl->thread, &attr, work_thread, (void *)data);
4006 if (ret) {
4007 cs_log("ERROR: can't create thread for %s (errno=%d %s)", action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret));
4008 if (data->ptr && len>0)
4009 free(data->ptr);
4010 free(data);
4011 } else
4012 pthread_detach(cl->thread);
4013
4014 pthread_attr_destroy(&attr);
4015
4016 cl->thread_active = 1;
4017 pthread_mutex_unlock(&cl->thread_lock);
4018}
4019
4020static void * check_thread(void) {
4021 int32_t time_to_check, next_check, ecmc_next, msec_wait = 3000;
4022 struct timeb t_now, tbc, ecmc_time;
4023#ifdef CS_ANTICASC
4024 int32_t ac_next;
4025 struct timeb ac_time;
4026#endif
4027 ECM_REQUEST *er = NULL;
4028 time_t ecm_timeout;
4029 time_t ecm_mintimeout;
4030 struct timespec ts;
4031 struct s_client *cl = create_client(first_client->ip);
4032 cl->typ = 's';
4033#ifdef WEBIF
4034 cl->wihidden = 1;
4035#endif
4036 cl->thread = pthread_self();
4037
4038 timecheck_client = cl;
4039
4040#ifdef CS_ANTICASC
4041 cs_ftime(&ac_time);
4042 add_ms_to_timeb(&ac_time, cfg.ac_stime*60*1000);
4043#endif
4044
4045 cs_ftime(&ecmc_time);
4046 add_ms_to_timeb(&ecmc_time, 1000);
4047
4048 while(1) {
4049 ts.tv_sec = msec_wait/1000;
4050 ts.tv_nsec = (msec_wait % 1000) * 1000000L;
4051 pthread_mutex_lock(&cl->thread_lock);
4052 cl->thread_active = 2;
4053 pthread_mutex_unlock(&cl->thread_lock);
4054 nanosleep(&ts, NULL);
4055 pthread_mutex_lock(&cl->thread_lock);
4056 cl->thread_active = 1;
4057 pthread_mutex_unlock(&cl->thread_lock);
4058
4059 next_check = 0;
4060#ifdef CS_ANTICASC
4061 ac_next = 0;
4062#endif
4063 ecmc_next = 0;
4064 msec_wait = 0;
4065
4066 cs_ftime(&t_now);
4067 cs_readlock(&ecmcache_lock);
4068
4069 for (er = ecmcwcache; er; er = er->next) {
4070 if (er->rc < E_99 || !er->l || !er->matching_rdr) //ignore CACHEEX pending ECMs
4071 continue;
4072
4073 tbc = er->tps;
4074#ifdef CS_CACHEEX
4075 time_to_check = add_ms_to_timeb(&tbc, (er->stage < 2) ? cfg.cacheex_wait_time:((er->stage < 4) ? cfg.ftimeout : cfg.ctimeout));
4076#else
4077 time_to_check = add_ms_to_timeb(&tbc, ((er->stage < 4) ? cfg.ftimeout : cfg.ctimeout));
4078#endif
4079
4080 if (comp_timeb(&t_now, &tbc) >= 0) {
4081 if (er->stage < 4) {
4082 cs_debug_mask(D_TRACE, "fallback for %s %04X&%06X/%04X/%04X ecm=%04X", username(er->client), er->caid, er->prid, er->pid, er->srvid, htons(er->checksum));
4083 if (er->rc >= E_UNHANDLED) //do not request rc=99
4084 request_cw(er);
4085
4086 tbc = er->tps;
4087 time_to_check = add_ms_to_timeb(&tbc, cfg.ctimeout);
4088 } else {
4089 if (er->client) {
4090 cs_debug_mask(D_TRACE, "timeout for %s %04X&%06X/%04X/%04X ecm=%04X", username(er->client), er->caid, er->prid, er->pid, er->srvid, htons(er->checksum));
4091 write_ecm_answer(NULL, er, E_TIMEOUT, 0, NULL, NULL);
4092 }
4093#ifdef WITH_LB
4094 if (!er->ecmcacheptr) { //do not add stat for cache entries:
4095 //because of lb, send E_TIMEOUT for all readers:
4096 struct s_ecm_answer *ea_list;
4097
4098 for(ea_list = er->matching_rdr; ea_list; ea_list = ea_list->next) {
4099 if ((ea_list->status & (REQUEST_SENT|REQUEST_ANSWERED)) == REQUEST_SENT) //Request send, but no answer!
4100 send_reader_stat(ea_list->reader, er, NULL, E_TIMEOUT);
4101 }
4102 }
4103#endif
4104
4105 time_to_check = 0;
4106 }
4107 }
4108 if (!next_check || (time_to_check > 0 && time_to_check < next_check))
4109 next_check = time_to_check;
4110 }
4111 cs_readunlock(&ecmcache_lock);
4112
4113#ifdef CS_ANTICASC
4114 if ((ac_next = comp_timeb(&ac_time, &t_now)) <= 10) {
4115 if (cfg.ac_enabled)
4116 ac_do_stat();
4117 cs_ftime(&ac_time);
4118 ac_next = add_ms_to_timeb(&ac_time, cfg.ac_stime*60*1000);
4119 }
4120#endif
4121
4122 if ((ecmc_next = comp_timeb(&ecmc_time, &t_now)) <= 10) {
4123 ecm_timeout = t_now.time-cfg.max_cache_time;
4124 ecm_mintimeout = t_now.time-(cfg.ctimeout/1000+2);
4125 uint32_t count = 0;
4126
4127 struct ecm_request_t *ecm, *ecmt=NULL, *prv;
4128 cs_readlock(&ecmcache_lock);
4129 for (ecm = ecmcwcache, prv = NULL; ecm; prv = ecm, ecm = ecm->next, count++) {
4130 if (ecm->tps.time < ecm_timeout || (ecm->tps.time<ecm_mintimeout && count>cfg.max_cache_count)) {
4131 cs_readunlock(&ecmcache_lock);
4132 cs_writelock(&ecmcache_lock);
4133 ecmt = ecm;
4134 if (prv)
4135 prv->next = NULL;
4136 else
4137 ecmcwcache = NULL;
4138 cs_writeunlock(&ecmcache_lock);
4139 break;
4140 }
4141 }
4142 if (!ecmt)
4143 cs_readunlock(&ecmcache_lock);
4144 ecmcwcache_size = count;
4145
4146 while (ecmt) {
4147 ecm = ecmt->next;
4148 free_ecm(ecmt);
4149 ecmt = ecm;
4150 }
4151
4152 cs_ftime(&ecmc_time);
4153 ecmc_next = add_ms_to_timeb(&ecmc_time, 1000);
4154 }
4155
4156 msec_wait = next_check;
4157
4158#ifdef CS_ANTICASC
4159 if (!msec_wait || (ac_next > 0 && ac_next < msec_wait))
4160 msec_wait = ac_next;
4161#endif
4162
4163 if (!msec_wait || (ecmc_next > 0 && ecmc_next < msec_wait))
4164 msec_wait = ecmc_next;
4165
4166 if (!msec_wait)
4167 msec_wait = 3000;
4168 }
4169 add_garbage(cl);
4170 timecheck_client = NULL;
4171 return NULL;
4172}
4173
4174static uint32_t resize_pfd_cllist(struct pollfd **pfd, struct s_client ***cl_list, uint32_t old_size, uint32_t new_size) {
4175 if (old_size != new_size) {
4176 struct pollfd *pfd_new = cs_malloc(&pfd_new, new_size*sizeof(struct pollfd), 0);
4177 struct s_client **cl_list_new = cs_malloc(&cl_list_new, new_size*sizeof(cl_list), 0);
4178 if (old_size > 0) {
4179 memcpy(pfd_new, *pfd, old_size*sizeof(struct pollfd));
4180 memcpy(cl_list_new, *cl_list, old_size*sizeof(cl_list));
4181 free(*pfd);
4182 free(*cl_list);
4183 }
4184 *pfd = pfd_new;
4185 *cl_list = cl_list_new;
4186 }
4187 return new_size;
4188}
4189
4190static uint32_t chk_resize_cllist(struct pollfd **pfd, struct s_client ***cl_list, uint32_t cur_size, uint32_t chk_size) {
4191 chk_size++;
4192 if (chk_size > cur_size) {
4193 uint32_t new_size = ((chk_size % 100)+1) * 100; //increase 100 step
4194 cur_size = resize_pfd_cllist(pfd, cl_list, cur_size, new_size);
4195 }
4196 return cur_size;
4197}
4198
4199void * client_check(void) {
4200 int32_t i, k, j, rc, pfdcount = 0;
4201 struct s_client *cl;
4202 struct s_reader *rdr;
4203 struct pollfd *pfd;
4204 struct s_client **cl_list;
4205 uint32_t cl_size = 0;
4206
4207 char buf[10];
4208
4209 if (pipe(thread_pipe) == -1) {
4210 printf("cannot create pipe, errno=%d\n", errno);
4211 exit(1);
4212 }
4213
4214 cl_size = chk_resize_cllist(&pfd, &cl_list, 0, 100);
4215
4216 pfd[pfdcount].fd = thread_pipe[0];
4217 pfd[pfdcount].events = POLLIN | POLLPRI | POLLHUP;
4218 cl_list[pfdcount] = NULL;
4219
4220 while (!exit_oscam) {
4221 pfdcount = 1;
4222
4223 //connected tcp clients
4224 for (cl=first_client->next; cl; cl=cl->next) {
4225 if (cl->init_done && !cl->kill && cl->pfd && cl->typ=='c' && !cl->is_udp) {
4226 if (cl->pfd && !cl->thread_active) {
4227 cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
4228 cl_list[pfdcount] = cl;
4229 pfd[pfdcount].fd = cl->pfd;
4230 pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP;
4231 }
4232 }
4233 //reader:
4234 //TCP:
4235 // - TCP socket must be connected
4236 // - no active init thread
4237 //UDP:
4238 // - connection status ignored
4239 // - no active init thread
4240 rdr = cl->reader;
4241 if (rdr && cl->typ=='p' && cl->init_done) {
4242 if (cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type==MOD_CONN_TCP)||(rdr->ph.type==MOD_CONN_UDP))) {
4243 cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
4244 cl_list[pfdcount] = cl;
4245 pfd[pfdcount].fd = cl->pfd;
4246 pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP;
4247 }
4248 }
4249 }
4250
4251 //server (new tcp connections or udp messages)
4252 for (k=0; k < CS_MAX_MOD; k++) {
4253 if ( (ph[k].type & MOD_CONN_NET) && ph[k].ptab ) {
4254 for (j=0; j<ph[k].ptab->nports; j++) {
4255 if (ph[k].ptab->ports[j].fd) {
4256 cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
4257 cl_list[pfdcount] = NULL;
4258 pfd[pfdcount].fd = ph[k].ptab->ports[j].fd;
4259 pfd[pfdcount++].events = POLLIN | POLLPRI | POLLHUP;
4260
4261 }
4262 }
4263 }
4264 }
4265
4266 if (pfdcount >= 1024)
4267 cs_log("WARNING: too many users!");
4268
4269 rc = poll(pfd, pfdcount, 5000);
4270
4271 if (rc<1)
4272 continue;
4273
4274 for (i=0; i<pfdcount; i++) {
4275 //clients
4276 cl = cl_list[i];
4277 if (cl && !is_valid_client(cl))
4278 continue;
4279
4280 if (pfd[i].fd == thread_pipe[0] && (pfd[i].revents & (POLLIN | POLLPRI))) {
4281 // a thread ended and cl->pfd should be added to pollfd list again (thread_active==0)
4282 if(read(thread_pipe[0], buf, sizeof(buf)) == -1){
4283 cs_debug_mask(D_TRACE, "Reading from pipe failed (errno=%d %s)", errno, strerror(errno));
4284 }
4285 continue;
4286 }
4287
4288 //clients
4289 // message on an open tcp connection
4290 if (cl && cl->init_done && cl->pfd && (cl->typ == 'c' || cl->typ == 'm')) {
4291 if (pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL))) {
4292 //client disconnects
4293 kill_thread(cl);
4294 continue;
4295 }
4296 if (pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) {
4297 add_job(cl, ACTION_CLIENT_TCP, NULL, 0);
4298 }
4299 }
4300
4301
4302 //reader
4303 // either an ecm answer, a keepalive or connection closed from a proxy
4304 // physical reader ('r') should never send data without request
4305 rdr = NULL;
4306 struct s_client *cl2 = NULL;
4307 if (cl && cl->typ == 'p'){
4308 rdr = cl->reader;
4309 if(rdr)
4310 cl2 = rdr->client;
4311 }
4312
4313 if (rdr && cl2 && cl2->init_done) {
4314 if (cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL))) {
4315 //connection to remote proxy was closed
4316 //oscam should check for rdr->tcp_connected and reconnect on next ecm request sent to the proxy
4317 network_tcp_connection_close(rdr, "closed");
4318 cs_debug_mask(D_READER, "connection to %s closed.", rdr->label);
4319 }
4320 if (cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLIN | POLLPRI))) {
4321 add_job(cl2, ACTION_READER_REMOTE, NULL, 0);
4322 }
4323 }
4324
4325
4326 //server sockets
4327 // new connection on a tcp listen socket or new message on udp listen socket
4328 if (!cl && (pfd[i].revents & (POLLIN | POLLPRI))) {
4329 for (k=0; k<CS_MAX_MOD; k++) {
4330 if( (ph[k].type & MOD_CONN_NET) && ph[k].ptab ) {
4331 for ( j=0; j<ph[k].ptab->nports; j++ ) {
4332 if ( ph[k].ptab->ports[j].fd && pfd[i].fd == ph[k].ptab->ports[j].fd ) {
4333 accept_connection(k,j);
4334 }
4335 }
4336 }
4337 } // if (ph[i].type & MOD_CONN_NET)
4338 }
4339 }
4340 first_client->last=time((time_t *)0);
4341 }
4342 free(pfd);
4343 free(cl_list);
4344 return NULL;
4345}
4346
4347void * reader_check(void) {
4348 struct s_client *cl;
4349 struct s_reader *rdr;
4350 while (1) {
4351 for (cl=first_client->next; cl ; cl=cl->next) {
4352 if (!cl->thread_active)
4353 check_status(cl);
4354 }
4355 cs_readlock(&readerlist_lock);
4356 for (rdr=first_active_reader; rdr; rdr=rdr->next) {
4357 if (rdr->enable) {
4358 cl = rdr->client;
4359 if (!cl || cl->kill)
4360 restart_cardreader(rdr, 0);
4361 else if (!cl->thread_active)
4362 check_status(cl);
4363 }
4364 }
4365 cs_readunlock(&readerlist_lock);
4366 cs_sleepms(1000);
4367 }
4368}
4369
4370int32_t accept_connection(int32_t i, int32_t j) {
4371 struct sockaddr_in cad;
4372 int32_t scad = sizeof(cad), n;
4373
4374 if (ph[i].type==MOD_CONN_UDP) {
4375 uchar *buf = cs_malloc(&buf, 1024, -1);
4376 if ((n=recvfrom(ph[i].ptab->ports[j].fd, buf+3, 1024-3, 0, (struct sockaddr *)&cad, (socklen_t *)&scad))>0) {
4377 struct s_client *cl;
4378 cl=idx_from_ip(cad.sin_addr.s_addr, ntohs(cad.sin_port));
4379
4380 uint16_t rl;
4381 rl=n;
4382 buf[0]='U';
4383 memcpy(buf+1, &rl, 2);
4384
4385 if (cs_check_violation((uint32_t)cad.sin_addr.s_addr, ph[i].ptab->ports[j].s_port)) {
4386 free(buf);
4387 return 0;
4388 }
4389
4390 cs_debug_mask(D_TRACE, "got %d bytes from ip %s:%d", n, cs_inet_ntoa(cad.sin_addr.s_addr), cad.sin_port);
4391
4392 if (!cl) {
4393 cl = create_client(cad.sin_addr.s_addr);
4394 if (!cl) return 0;
4395
4396 cl->ctyp=i;
4397 cl->port_idx=j;
4398 cl->udp_fd=ph[i].ptab->ports[j].fd;
4399 cl->udp_sa=cad;
4400
4401 cl->port=ntohs(cad.sin_port);
4402 cl->typ='c';
4403
4404 add_job(cl, ACTION_CLIENT_INIT, NULL, 0);
4405 }
4406 add_job(cl, ACTION_CLIENT_UDP, buf, n+3);
4407 } else
4408 free(buf);
4409 } else { //TCP
4410 int32_t pfd3;
4411 if ((pfd3=accept(ph[i].ptab->ports[j].fd, (struct sockaddr *)&cad, (socklen_t *)&scad))>0) {
4412
4413 if (cs_check_violation((uint32_t)cad.sin_addr.s_addr, ph[i].ptab->ports[j].s_port)) {
4414 close(pfd3);
4415 return 0;
4416 }
4417
4418 struct s_client * cl = create_client(cad.sin_addr.s_addr);
4419 if (cl == NULL) {
4420 close(pfd3);
4421 return 0;
4422 }
4423
4424 int32_t flag = 1;
4425 setsockopt(pfd3, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
4426 setTCPTimeouts(pfd3);
4427
4428 cl->ctyp=i;
4429 cl->udp_fd=pfd3;
4430 cl->port_idx=j;
4431
4432 cl->pfd=pfd3;
4433 cl->port=ntohs(cad.sin_port);
4434 cl->typ='c';
4435
4436 add_job(cl, ACTION_CLIENT_INIT, NULL, 0);
4437 }
4438 }
4439 return 0;
4440}
4441
4442#ifdef WEBIF
4443static void restart_daemon()
4444{
4445 while (1) {
4446
4447 //start client process:
4448 pid_t pid = fork();
4449 if (!pid)
4450 return; //client process=oscam process
4451 if (pid < 0)
4452 exit(1);
4453
4454 //restart control process:
4455 int32_t res=0;
4456 int32_t status=0;
4457 do {
4458 res = waitpid(pid, &status, 0);
4459 if (res==-1) {
4460 if (errno!=EINTR)
4461 exit(1);
4462 }
4463 } while (res!=pid);
4464
4465 if (cs_restart_mode==2 && WIFSIGNALED(status) && WTERMSIG(status)==SIGSEGV)
4466 status=99; //restart on segfault!
4467 else
4468 status = WEXITSTATUS(status);
4469
4470 //status=99 restart oscam, all other->terminate
4471 if (status!=99) {
4472 exit(status);
4473 }
4474 }
4475}
4476#endif
4477
4478int32_t main (int32_t argc, char *argv[])
4479{
4480 prog_name = argv[0];
4481 if (pthread_key_create(&getclient, NULL)) {
4482 fprintf(stderr, "Could not create getclient, exiting...");
4483 exit(1);
4484 }
4485
4486#ifdef ARM
4487 cs_switch_led(LED1A, LED_DEFAULT);
4488 cs_switch_led(LED1A, LED_ON);
4489#endif
4490
4491 int32_t i, j, bg=0, gbdb=0;
4492
4493 void (*mod_def[])(struct s_module *)=
4494 {
4495#ifdef MODULE_MONITOR
4496 module_monitor,
4497#endif
4498#ifdef MODULE_CAMD33
4499 module_camd33,
4500#endif
4501#ifdef MODULE_CAMD35
4502 module_camd35,
4503#endif
4504#ifdef MODULE_CAMD35_TCP
4505 module_camd35_tcp,
4506#endif
4507#ifdef MODULE_NEWCAMD
4508 module_newcamd,
4509#endif
4510#ifdef MODULE_CCCAM
4511 module_cccam,
4512#endif
4513#ifdef MODULE_PANDORA
4514 module_pandora,
4515#endif
4516#ifdef CS_CACHEEX
4517 module_csp,
4518#endif
4519#ifdef MODULE_GBOX
4520 module_gbox,
4521#endif
4522#ifdef MODULE_CONSTCW
4523 module_constcw,
4524#endif
4525#ifdef MODULE_RADEGAST
4526 module_radegast,
4527#endif
4528#ifdef MODULE_SERIAL
4529 module_oscam_ser,
4530#endif
4531#ifdef HAVE_DVBAPI
4532 module_dvbapi,
4533#endif
4534 0
4535 };
4536
4537 void (*cardsystem_def[])(struct s_cardsystem *)=
4538 {
4539#ifdef READER_NAGRA
4540 reader_nagra,
4541#endif
4542#ifdef READER_IRDETO
4543 reader_irdeto,
4544#endif
4545#ifdef READER_CONAX
4546 reader_conax,
4547#endif
4548#ifdef READER_CRYPTOWORKS
4549 reader_cryptoworks,
4550#endif
4551#ifdef READER_SECA
4552 reader_seca,
4553#endif
4554#ifdef READER_VIACCESS
4555 reader_viaccess,
4556#endif
4557#ifdef READER_VIDEOGUARD
4558 reader_videoguard1,
4559 reader_videoguard2,
4560 reader_videoguard12,
4561#endif
4562#ifdef READER_DRE
4563 reader_dre,
4564#endif
4565#ifdef READER_TONGFANG
4566 reader_tongfang,
4567#endif
4568 0
4569 };
4570
4571 void (*cardreader_def[])(struct s_cardreader *)=
4572 {
4573#ifdef WITH_CARDREADER
4574 cardreader_mouse,
4575 cardreader_smargo,
4576#ifdef WITH_STAPI
4577 cardreader_stapi,
4578#endif
4579#endif
4580 0
4581 };
4582
4583 while ((i=getopt(argc, argv, "g:bsauc:t:d:r:w:hm:x"))!=EOF)
4584 {
4585 switch(i) {
4586 case 'g':
4587 gbdb=atoi(optarg);
4588 break;
4589 case 'b':
4590 bg=1;
4591 break;
4592 case 's':
4593 cs_capture_SEGV=1;
4594 break;
4595 case 'a':
4596 cs_dump_stack=1;
4597 break;
4598 case 'c':
4599 cs_strncpy(cs_confdir, optarg, sizeof(cs_confdir));
4600 break;
4601 case 'd':
4602 cs_dblevel=atoi(optarg);
4603 break;
4604 case 'r':
4605
4606#ifdef WEBIF
4607 cs_restart_mode=atoi(optarg);
4608#endif
4609 break;
4610 case 't':
4611 mkdir(optarg, S_IRWXU);
4612 j = open(optarg, O_RDONLY);
4613 if (j >= 0) {
4614 close(j);
4615 cs_strncpy(cs_tmpdir, optarg, sizeof(cs_tmpdir));
4616 } else {
4617 printf("WARNING: tmpdir does not exist. using default value.\n");
4618 }
4619 break;
4620 case 'w':
4621 cs_waittime=strtoul(optarg, NULL, 10);
4622 break;
4623#ifdef WEBIF
4624 case 'u':
4625 cs_http_use_utf8 = 1;
4626 printf("WARNING: Web interface UTF-8 mode enabled. Carefully read documentation as bugs may arise.\n");
4627 break;
4628#endif
4629 case 'm':
4630 printf("WARNING: -m parameter is deprecated, ignoring it.\n");
4631 break;
4632 case 'h':
4633 default :
4634 usage();
4635 }
4636 }
4637
4638
4639#ifdef OS_MACOSX
4640 if (bg && daemon_compat(1,0))
4641#else
4642 if (bg && daemon(1,0))
4643#endif
4644 {
4645 printf("Error starting in background (errno=%d: %s)", errno, strerror(errno));
4646 cs_exit(1);
4647 }
4648
4649#ifdef WEBIF
4650 if (cs_restart_mode)
4651 restart_daemon();
4652#endif
4653
4654 memset(&cfg, 0, sizeof(struct s_config));
4655
4656 if (cs_confdir[strlen(cs_confdir)]!='/') strcat(cs_confdir, "/");
4657 init_signal_pre(); // because log could cause SIGPIPE errors, init a signal handler first
4658 init_first_client();
4659 init_config();
4660 init_check();
4661#ifdef WITH_LB
4662 init_stat();
4663#endif
4664
4665 for (i=0; mod_def[i]; i++) // must be later BEFORE init_config()
4666 {
4667 memset(&ph[i], 0, sizeof(struct s_module));
4668 mod_def[i](&ph[i]);
4669 }
4670 for (i=0; cardsystem_def[i]; i++) // must be later BEFORE init_config()
4671 {
4672 memset(&cardsystem[i], 0, sizeof(struct s_cardsystem));
4673 cardsystem_def[i](&cardsystem[i]);
4674 }
4675
4676 for (i=0; cardreader_def[i]; i++) // must be later BEFORE init_config()
4677 {
4678 memset(&cardreader[i], 0, sizeof(struct s_cardreader));
4679 cardreader_def[i](&cardreader[i]);
4680 }
4681
4682 init_rnd();
4683 init_sidtab();
4684 init_readerdb();
4685 cfg.account = init_userdb();
4686 init_signal();
4687 init_srvid();
4688 init_tierid();
4689 //Todo #ifdef CCCAM
4690 init_provid();
4691
4692 start_garbage_collector(gbdb);
4693
4694 //set cacheex cccam+camd35 node id:
4695#ifdef CS_CACHEEX
4696#if defined MODULE_CAMD35 || defined MODULE_CAMD35_TCP
4697#ifdef MODULE_CCCAM
4698 cacheex_set_peer_id(cc_get_cccam_node_id());
4699#else
4700 cacheex_update_peer_id();
4701#endif
4702#endif
4703#endif
4704
4705 init_len4caid();
4706#ifdef IRDETO_GUESSING
4707 init_irdeto_guess_tab();
4708#endif
4709
4710 write_versionfile();
4711 server_pid = getpid();
4712
4713#ifdef ARM
4714 arm_led_start_thread();
4715#endif
4716
4717#if defined(AZBOX) && defined(HAVE_DVBAPI)
4718 openxcas_debug_message_onoff(1); // debug
4719
4720#ifdef WITH_CARDREADER
4721 if (openxcas_open_with_smartcard("oscamCAS") < 0) {
4722#else
4723 if (openxcas_open("oscamCAS") < 0) {
4724#endif
4725 cs_log("openxcas: could not init");
4726 }
4727#endif
4728
4729 global_whitelist_read();
4730#ifdef CS_CACHEEX
4731 cacheex_matcher_read();
4732#endif
4733
4734 for (i=0; i<CS_MAX_MOD; i++)
4735 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
4736 for(j=0; j<ph[i].ptab->nports; j++)
4737 {
4738 start_listener(&ph[i], j);
4739 }
4740
4741 //set time for server to now to avoid 0 in monitor/webif
4742 first_client->last=time((time_t *)0);
4743
4744#ifdef WEBIF
4745 if(cfg.http_port == 0)
4746 cs_log("http disabled");
4747 else
4748 start_thread((void *) &http_srv, "http");
4749#endif
4750 start_thread((void *) &reader_check, "reader check");
4751 start_thread((void *) &check_thread, "check");
4752#ifdef LCDSUPPORT
4753 if(cfg.enablelcd)
4754 start_lcd_thread();
4755#endif
4756
4757 init_cardreader();
4758
4759 cs_waitforcardinit();
4760
4761#ifdef ARM
4762 if(cfg.enableled == 1){
4763 cs_switch_led(LED1A, LED_OFF);
4764 cs_switch_led(LED1B, LED_ON);
4765 }
4766#endif
4767
4768#ifdef QBOXHD
4769 if(cfg.enableled == 2){
4770 cs_log("QboxHD LED enabled");
4771 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_FAST);
4772 qboxhd_led_blink(QBOXHD_LED_COLOR_RED,QBOXHD_LED_BLINK_FAST);
4773 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_FAST);
4774 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE,QBOXHD_LED_BLINK_FAST);
4775 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_FAST);
4776 }
4777#endif
4778
4779#ifdef CS_ANTICASC
4780 if( !cfg.ac_enabled )
4781 cs_log("anti cascading disabled");
4782 else {
4783 init_ac();
4784 ac_init_stat();
4785 }
4786#endif
4787
4788 for (i=0; i<CS_MAX_MOD; i++)
4789 if (ph[i].type & MOD_CONN_SERIAL) // for now: oscam_ser only
4790 if (ph[i].s_handler)
4791 ph[i].s_handler(NULL, NULL, i);
4792
4793 // main loop function
4794 client_check();
4795
4796
4797#if defined(AZBOX) && defined(HAVE_DVBAPI)
4798 if (openxcas_close() < 0) {
4799 cs_log("openxcas: could not close");
4800 }
4801#endif
4802
4803 cs_cleanup();
4804 while(ll_count(log_list) > 0)
4805 cs_sleepms(1);
4806 stop_garbage_collector();
4807
4808 return exit_oscam;
4809}
4810
4811void cs_exit_oscam()
4812{
4813 exit_oscam=1;
4814 cs_log("exit oscam requested");
4815}
4816
4817#ifdef WEBIF
4818void cs_restart_oscam()
4819{
4820 exit_oscam=99;
4821 cs_log("restart oscam requested");
4822}
4823
4824int32_t cs_get_restartmode() {
4825 return cs_restart_mode;
4826}
4827
4828#endif
4829
4830#ifdef ARM
4831static void cs_switch_led_from_thread(int32_t led, int32_t action) {
4832
4833 if(action < 2) { // only LED_ON and LED_OFF
4834 char ledfile[256];
4835 FILE *f;
4836
4837 #ifdef DOCKSTAR
4838 switch(led){
4839 case LED1A:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
4840 break;
4841 case LED1B:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
4842 break;
4843 case LED2:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
4844 break;
4845 case LED3:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
4846 break;
4847 }
4848 #elif WRT350NV2
4849 switch(led){
4850 case LED1A:snprintf(ledfile, 255, "/sys/class/leds/wrt350nv2:orange:power/brightness");
4851 break;
4852 case LED1B:snprintf(ledfile, 255, "/sys/class/leds/wrt350nv2:green:power/brightness");
4853 break;
4854 case LED2:snprintf(ledfile, 255, "/sys/class/leds/wrt350nv2:green:wireless/brightness");
4855 break;
4856 case LED3:snprintf(ledfile, 255, "/sys/class/leds/wrt350nv2:green:security/brightness");
4857 break;
4858 }
4859 #else
4860 switch(led){
4861 case LED1A:snprintf(ledfile, 255, "/sys/class/leds/nslu2:red:status/brightness");
4862 break;
4863 case LED1B:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:ready/brightness");
4864 break;
4865 case LED2:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-1/brightness");
4866 break;
4867 case LED3:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-2/brightness");
4868 break;
4869 }
4870 #endif
4871
4872 if (!(f=fopen(ledfile, "w"))){
4873 // FIXME: sometimes cs_log was not available when calling cs_switch_led -> signal 11
4874 // cs_log("Cannot open file \"%s\" (errno=%d %s)", ledfile, errno, strerror(errno));
4875 return;
4876 }
4877 fprintf(f,"%d", action);
4878 fclose(f);
4879 } else { // LED Macros
4880 switch(action){
4881 case LED_DEFAULT:
4882 cs_switch_led_from_thread(LED1A, LED_OFF);
4883 cs_switch_led_from_thread(LED1B, LED_OFF);
4884 cs_switch_led_from_thread(LED2, LED_ON);
4885 cs_switch_led_from_thread(LED3, LED_OFF);
4886 break;
4887 case LED_BLINK_OFF:
4888 cs_switch_led_from_thread(led, LED_OFF);
4889 cs_sleepms(100);
4890 cs_switch_led_from_thread(led, LED_ON);
4891 break;
4892 case LED_BLINK_ON:
4893 cs_switch_led_from_thread(led, LED_ON);
4894 cs_sleepms(300);
4895 cs_switch_led_from_thread(led, LED_OFF);
4896 break;
4897 }
4898 }
4899}
4900
4901static void* arm_led_thread_main() {
4902 uint8_t running = 1;
4903 while (running) {
4904 LL_ITER iter = ll_iter_create(arm_led_actions);
4905 struct s_arm_led *arm_led;
4906 while ((arm_led = ll_iter_next(&iter))) {
4907 int32_t led, action;
4908 time_t now, start;
4909 led = arm_led->led;
4910 action = arm_led->action;
4911 now = time((time_t)0);
4912 start = arm_led->start_time;
4913 ll_iter_remove_data(&iter);
4914 if (action == LED_STOP_THREAD) {
4915 running = 0;
4916 break;
4917 }
4918 if (now - start < ARM_LED_TIMEOUT) {
4919 cs_switch_led_from_thread(led, action);
4920 }
4921 }
4922 if (running) {
4923 sleep(60);
4924 }
4925 }
4926 ll_clear_data(arm_led_actions);
4927 pthread_exit(NULL);
4928 return NULL;
4929}
4930
4931void arm_led_start_thread() {
4932 // call this after signal handling is done
4933 if ( ! arm_led_actions ) {
4934 arm_led_actions = ll_create("arm_led_actions");
4935 }
4936 pthread_attr_t attr;
4937 pthread_attr_init(&attr);
4938 cs_log("starting thread arm_led_thread");
4939#ifndef TUXBOX
4940 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
4941#endif
4942 int32_t ret = pthread_create(&arm_led_thread, &attr, arm_led_thread_main, NULL);
4943 if (ret)
4944 cs_log("ERROR: can't create arm_led_thread thread (errno=%d %s)", ret, strerror(ret));
4945 else {
4946 cs_log("arm_led_thread thread started");
4947 pthread_detach(arm_led_thread);
4948 }
4949 pthread_attr_destroy(&attr);
4950}
4951
4952void arm_led_stop_thread() {
4953 cs_switch_led(0, LED_STOP_THREAD);
4954}
4955
4956void cs_switch_led(int32_t led, int32_t action) {
4957 struct s_arm_led *arm_led = (struct s_arm_led *)malloc(sizeof(struct s_arm_led));
4958 if (arm_led == NULL) {
4959 cs_log("ERROR: cs_switch_led out of memory");
4960 return;
4961 }
4962 arm_led->start_time = time((time_t)0);
4963 arm_led->led = led;
4964 arm_led->action = action;
4965 if ( ! arm_led_actions ) {
4966 arm_led_actions = ll_create("arm_led_actions");
4967 }
4968 ll_append(arm_led_actions, (void *)arm_led);
4969 if (arm_led_thread) {
4970 // arm_led_thread_main is not started at oscam startup
4971 // when first cs_switch_led calls happen
4972 pthread_kill(arm_led_thread, OSCAM_SIGNAL_WAKEUP);
4973 }
4974}
4975#endif
4976
4977#ifdef QBOXHD
4978void qboxhd_led_blink(int32_t color, int32_t duration) {
4979 int32_t f;
4980
4981 // try QboxHD-MINI first
4982 if ( (f = open ( QBOXHDMINI_LED_DEVICE, O_RDWR |O_NONBLOCK )) > -1 ) {
4983 qboxhdmini_led_color_struct qbminiled;
4984 uint32_t qboxhdmini_color = 0x000000;
4985
4986 if (color != QBOXHD_LED_COLOR_OFF) {
4987 switch(color) {
4988 case QBOXHD_LED_COLOR_RED:
4989 qboxhdmini_color = QBOXHDMINI_LED_COLOR_RED;
4990 break;
4991 case QBOXHD_LED_COLOR_GREEN:
4992 qboxhdmini_color = QBOXHDMINI_LED_COLOR_GREEN;
4993 break;
4994 case QBOXHD_LED_COLOR_BLUE:
4995 qboxhdmini_color = QBOXHDMINI_LED_COLOR_BLUE;
4996 break;
4997 case QBOXHD_LED_COLOR_YELLOW:
4998 qboxhdmini_color = QBOXHDMINI_LED_COLOR_YELLOW;
4999 break;
5000 case QBOXHD_LED_COLOR_MAGENTA:
5001 qboxhdmini_color = QBOXHDMINI_LED_COLOR_MAGENTA;
5002 break;
5003 }
5004
5005 // set LED on with color
5006 qbminiled.red = (uchar)((qboxhdmini_color&0xFF0000)>>16); // R
5007 qbminiled.green = (uchar)((qboxhdmini_color&0x00FF00)>>8); // G
5008 qbminiled.blue = (uchar)(qboxhdmini_color&0x0000FF); // B
5009
5010 ioctl(f,QBOXHDMINI_IOSET_RGB,&qbminiled);
5011 cs_sleepms(duration);
5012 }
5013
5014 // set LED off
5015 qbminiled.red = 0;
5016 qbminiled.green = 0;
5017 qbminiled.blue = 0;
5018
5019 ioctl(f,QBOXHDMINI_IOSET_RGB,&qbminiled);
5020 close(f);
5021
5022 } else if ( (f = open ( QBOXHD_LED_DEVICE, O_RDWR |O_NONBLOCK )) > -1 ) {
5023
5024 qboxhd_led_color_struct qbled;
5025
5026 if (color != QBOXHD_LED_COLOR_OFF) {
5027 // set LED on with color
5028 qbled.H = color;
5029 qbled.S = 99;
5030 qbled.V = 99;
5031 ioctl(f,QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
5032 cs_sleepms(duration);
5033 }
5034
5035 // set LED off
5036 qbled.H = 0;
5037 qbled.S = 0;
5038 qbled.V = 0;
5039 ioctl(f,QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
5040 close(f);
5041 }
5042
5043 return;
5044}
5045#endif
Note: See TracBrowser for help on using the repository browser.