source: trunk/oscam.c@ 4011

Last change on this file since 4011 was 4011, checked in by _network, 10 years ago

revert last change

File size: 84.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#ifdef AZBOX
5# include "openxcas/openxcas_api.h"
6#endif
7#ifdef CS_WITH_GBOX
8# include "csgbox/gbox.h"
9# define CS_VERSION_X CS_VERSION "-gbx-" GBXVERSION
10#else
11# define CS_VERSION_X CS_VERSION
12#endif
13
14extern void cs_statistics(struct s_client * client);
15
16/*****************************************************************************
17 Globals
18*****************************************************************************/
19struct s_module ph[CS_MAX_MOD]; // Protocols
20struct s_cardsystem cardsystem[CS_MAX_MOD]; // Protocols
21struct s_client * first_client = NULL; //Pointer to clients list, first client is master
22struct s_reader * first_reader = NULL;
23
24ushort len4caid[256]; // table for guessing caid (by len)
25char cs_confdir[128]=CS_CONFDIR;
26int cs_dblevel=0; // Debug Level (TODO !!)
27char cs_tmpdir[200]={0x00};
28pthread_mutex_t gethostbyname_lock;
29pthread_mutex_t cwcache_lock;
30pthread_key_t getclient;
31
32//Cache for **found** cws:
33struct s_ecm *cwcache;
34struct s_ecm *cwidx;
35
36//Cache for **requesting** ecms:
37struct s_ecm *ecmcache;
38struct s_ecm *ecmidx;
39pthread_mutex_t ecmcache_lock;
40
41#ifdef CS_WITH_GBOX
42struct card_struct Cards[CS_MAXCARDS];
43//struct idstore_struct idstore[CS_MAXPID];
44unsigned long IgnoreList[CS_MAXIGNORE];
45#endif
46
47struct s_config *cfg;
48#ifdef CS_LOGHISTORY
49int loghistidx; // ptr to current entry
50char loghist[CS_MAXLOGHIST*CS_LOGHISTSIZE]; // ptr of log-history
51#endif
52
53int get_ridx(struct s_reader *reader) {
54 int i;
55 struct s_reader *rdr;
56 for (i=0,rdr=first_reader; rdr ; rdr=rdr->next, i++)
57 if (reader == rdr)
58 return i;
59 return -1;
60}
61
62int get_nr_of_readers() {
63 int i;
64 struct s_reader *rdr;
65 for (i=0,rdr=first_reader; rdr ; rdr=rdr->next, i++);
66 return i;
67}
68
69int get_threadnum(struct s_client *client) {
70 struct s_client *cl;
71 int count=0;
72
73 for (cl=first_client->next; cl ; cl=cl->next) {
74 if (cl->typ==client->typ)
75 count++;
76 if(cl==client)
77 return count;
78 }
79 return 0;
80}
81
82struct s_client * cur_client(void)
83{
84 return (struct s_client *) pthread_getspecific(getclient);
85}
86
87int cs_check_violation(uint ip) {
88 if (cfg->failbantime) {
89
90 time_t now = time((time_t)0);
91 LLIST_D__ITR itr;
92 V_BAN *v_ban_entry = llist_itr_init(cfg->v_list, &itr);
93
94 while (v_ban_entry) {
95 if (ip == v_ban_entry->v_ip) {
96 if ((now - v_ban_entry->v_time) >= (cfg->failbantime * 60)) {
97 // housekeeping
98 free(v_ban_entry);
99 llist_itr_remove(&itr);
100 return 0;
101 }
102 cs_debug_mask(D_TRACE, "failban: banned ip %s - %ld seconds left",
103 cs_inet_ntoa(v_ban_entry->v_ip),(cfg->failbantime * 60) - (now - v_ban_entry->v_time));
104 return 1;
105 }
106 v_ban_entry = llist_itr_next(&itr);
107 }
108 return 0;
109 }
110 return 0;
111}
112
113void cs_add_violation(uint ip) {
114 if (cfg->failbantime) {
115
116 if (!cfg->v_list)
117 cfg->v_list = llist_create();
118
119 LLIST_D__ITR itr;
120 V_BAN *v_ban_entry = llist_itr_init(cfg->v_list, &itr);
121 while (v_ban_entry) {
122 if (ip == v_ban_entry->v_ip) {
123 cs_debug_mask(D_TRACE, "failban: banned ip %s - already exist in list", cs_inet_ntoa(v_ban_entry->v_ip));
124 return ;
125 }
126 v_ban_entry = llist_itr_next(&itr);
127 }
128
129 v_ban_entry = malloc(sizeof(V_BAN));
130 memset(v_ban_entry, 0, sizeof(V_BAN));
131
132 v_ban_entry->v_time = time((time_t *)0);
133 v_ban_entry->v_ip = ip;
134
135 llist_append(cfg->v_list, v_ban_entry);
136
137 cs_debug_mask(D_TRACE, "failban: ban ip %s with timestamp %d", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_time);
138
139 }
140}
141//Alno Test End
142/*****************************************************************************
143 Statics
144*****************************************************************************/
145static const char *logo = " ___ ____ ___ \n / _ \\/ ___| / __|__ _ _ __ ___ \n| | | \\___ \\| | / _` | '_ ` _ \\ \n| |_| |___) | |_| (_| | | | | | |\n \\___/|____/ \\___\\__,_|_| |_| |_|\n";
146
147static void usage()
148{
149 fprintf(stderr, "%s\n\n", logo);
150 fprintf(stderr, "OSCam cardserver v%s, build #%s (%s) - (w) 2009-2010 streamboard SVN\n", CS_VERSION_X, CS_SVN_VERSION, CS_OSTYPE);
151 fprintf(stderr, "\tsee http://streamboard.gmc.to:8001/wiki/ for more details\n");
152 fprintf(stderr, "\tbased on streamboard mp-cardserver v0.9d - (w) 2004-2007 by dukat\n");
153 fprintf(stderr, "\tinbuilt modules: ");
154#ifdef WEBIF
155 #ifdef WITH_SSL
156 fprintf(stderr, "webinterface with ssl ");
157 #else
158 fprintf(stderr, "webinterface ");
159 #endif
160#endif
161#ifdef HAVE_DVBAPI
162#ifdef WITH_STAPI
163 fprintf(stderr, "dvbapi with stapi ");
164#else
165 fprintf(stderr, "dvbapi ");
166#endif
167#endif
168#ifdef IRDETO_GUESSING
169 fprintf(stderr, "irdeto-guessing ");
170#endif
171#ifdef CS_ANTICASC
172 fprintf(stderr, "anticascading ");
173#endif
174#ifdef WITH_DEBUG
175 fprintf(stderr, "debug ");
176#endif
177#ifdef CS_LED
178 fprintf(stderr, "led-trigger ");
179#endif
180#ifdef CS_WITH_DOUBLECHECK
181 fprintf(stderr, "doublecheck ");
182#endif
183#ifdef QBOXHD_LED
184 fprintf(stderr, "QboxHD-led-trigger ");
185#endif
186#ifdef CS_LOGHISTORY
187 fprintf(stderr, "loghistory ");
188#endif
189#ifdef LIBUSB
190 fprintf(stderr, "smartreader ");
191#endif
192#ifdef HAVE_PCSC
193 fprintf(stderr, "pcsc ");
194#endif
195#ifdef CS_WITH_GBOX
196 fprintf(stderr, "gbox ");
197#endif
198 fprintf(stderr, "\n\n");
199 fprintf(stderr, "oscam [-b] [-c config-dir] [-d]");
200 fprintf(stderr, " [-h]");
201 fprintf(stderr, "\n\n\t-b : start in background\n");
202 fprintf(stderr, "\t-c <dir> : read configuration from <dir>\n");
203 fprintf(stderr, "\t default = %s\n", CS_CONFDIR);
204 fprintf(stderr, "\t-t <dir> : tmp dir <dir>\n");
205#ifdef CS_CYGWIN32
206 fprintf(stderr, "\t default = (OS-TMP)\n");
207#else
208 fprintf(stderr, "\t default = /tmp/.oscam\n");
209#endif
210 fprintf(stderr, "\t-d <level> : debug level mask\n");
211 fprintf(stderr, "\t 0 = no debugging (default)\n");
212 fprintf(stderr, "\t 1 = detailed error messages\n");
213 fprintf(stderr, "\t 2 = ATR parsing info, ECM, EMM and CW dumps\n");
214 fprintf(stderr, "\t 4 = traffic from/to the reader\n");
215 fprintf(stderr, "\t 8 = traffic from/to the clients\n");
216 fprintf(stderr, "\t 16 = traffic to the reader-device on IFD layer\n");
217 fprintf(stderr, "\t 32 = traffic to the reader-device on I/O layer\n");
218 fprintf(stderr, "\t 64 = EMM logging\n");
219 fprintf(stderr, "\t 255 = debug all\n");
220 fprintf(stderr, "\t-h : show this help\n");
221 fprintf(stderr, "\n");
222 exit(1);
223}
224
225#ifdef NEED_DAEMON
226#ifdef OS_MACOSX
227// this is done because daemon is being deprecated starting with 10.5 and -Werror will always trigger an error
228static int daemon_compat(int nochdir, int noclose)
229#else
230static int daemon(int nochdir, int noclose)
231#endif
232{
233 int fd;
234
235 switch (fork())
236 {
237 case -1: return (-1);
238 case 0: break;
239 default: _exit(0);
240 }
241
242 if (setsid()==(-1))
243 return(-1);
244
245 if (!nochdir)
246 (void)chdir("/");
247
248 if (!noclose && (fd=open("/dev/null", O_RDWR, 0)) != -1)
249 {
250 (void)dup2(fd, STDIN_FILENO);
251 (void)dup2(fd, STDOUT_FILENO);
252 (void)dup2(fd, STDERR_FILENO);
253 if (fd>2)
254 (void)close(fd);
255 }
256 return(0);
257}
258#endif
259
260int recv_from_udpipe(uchar *buf)
261{
262 unsigned short n;
263 if (buf[0]!='U')
264 {
265 cs_log("INTERNAL PIPE-ERROR");
266 cs_exit(1);
267 }
268 memcpy(&n, buf+1, 2);
269
270 memmove(buf, buf+3, n);
271
272 return n;
273}
274
275char *username(struct s_client * client)
276{
277 if (client->usr[0])
278 return(client->usr);
279 else
280 return("anonymous");
281}
282
283static struct s_client * idx_from_ip(in_addr_t ip, in_port_t port)
284{
285 struct s_client *cl;
286 for (cl=first_client; cl ; cl=cl->next)
287 if ((cl->ip==ip) && (cl->port==port) && ((cl->typ=='c') || (cl->typ=='m')))
288 return cl;
289 return NULL;
290}
291
292struct s_client * get_client_by_tid(unsigned long tid) //FIXME untested!! no longer pid in output...
293{
294 struct s_client *cl;
295 for (cl=first_client; cl ; cl=cl->next)
296 if ((unsigned long)(cl->thread)==tid)
297 return cl;
298 return NULL;
299}
300
301static long chk_caid(ushort caid, CAIDTAB *ctab)
302{
303 int n;
304 long rc;
305 for (rc=(-1), n=0; (n<CS_MAXCAIDTAB) && (rc<0); n++)
306 if ((caid & ctab->mask[n]) == ctab->caid[n])
307 rc=ctab->cmap[n] ? ctab->cmap[n] : caid;
308 return(rc);
309}
310
311int chk_bcaid(ECM_REQUEST *er, CAIDTAB *ctab)
312{
313 long caid;
314 if ((caid=chk_caid(er->caid, ctab))<0)
315 return(0);
316 er->caid=caid;
317 return(1);
318}
319
320/*
321 * void set_signal_handler(int sig, int flags, void (*sighandler)(int))
322 * flags: 1 = restart, 2 = don't modify if SIG_IGN, may be combined
323 */
324void set_signal_handler(int sig, int flags, void (*sighandler))
325{
326#ifdef CS_SIGBSD
327 if ((signal(sig, sighandler)==SIG_IGN) && (flags & 2))
328 {
329 signal(sig, SIG_IGN);
330 siginterrupt(sig, 0);
331 }
332 else
333 siginterrupt(sig, (flags & 1) ? 0 : 1);
334#else
335 struct sigaction sa;
336 sigaction(sig, (struct sigaction *) 0, &sa);
337 if (!((flags & 2) && (sa.sa_handler==SIG_IGN)))
338 {
339 sigemptyset(&sa.sa_mask);
340 sa.sa_flags=(flags & 1) ? SA_RESTART : 0;
341 sa.sa_handler=sighandler;
342 sigaction(sig, &sa, (struct sigaction *) 0);
343 }
344#endif
345}
346
347static void cs_master_alarm()
348{
349 cs_log("PANIC: master deadlock!");
350 fprintf(stderr, "PANIC: master deadlock!");
351 fflush(stderr);
352}
353
354static void cs_sigpipe()
355{
356 cs_log("Got sigpipe signal -> captured");
357}
358
359void cs_accounts_chk()
360{
361 init_userdb(&cfg->account);
362 cs_reinit_clients();
363#ifdef CS_ANTICASC
364// struct s_client *cl;
365// for (cl=first_client->next; cl ; cl=cl->next)
366// if (cl->typ=='a')
367// break;
368 ac_clear();
369#endif
370}
371
372static void nullclose(int *fd)
373{
374 //if closing an already closed pipe, we get a sigpipe signal, and this causes a cs_exit
375 //and this causes a close and this causes a sigpipe...and so on
376 int f = *fd;
377 *fd = 0; //so first null client-fd
378 close(f); //then close fd
379}
380
381static void cleanup_thread(struct s_client *cl)
382{
383 struct s_client *prev, *cl2;
384 for (prev=first_client, cl2=first_client->next; prev->next != NULL; prev=prev->next, cl2=cl2->next)
385 if (cl == cl2)
386 break;
387 if (cl != cl2)
388 cs_log("FATAL ERROR: could not find client to remove from list.");
389 else
390 prev->next = cl2->next; //remove client from list
391
392 cs_sleepms(2000); //wait some time before cleanup to prevent segfaults
393 if(ph[cl->ctyp].cleanup) ph[cl->ctyp].cleanup(cl);
394 NULLFREE(cl->ecmtask);
395 NULLFREE(cl->emmcache);
396 NULLFREE(cl->req);
397 NULLFREE(cl->cc);
398 if(cl->pfd) nullclose(&cl->pfd); //Closing Network socket
399 if(cl->fd_m2c_c) nullclose(&cl->fd_m2c_c); //Closing client read fd
400 if(cl->fd_m2c) nullclose(&cl->fd_m2c); //Closing client read fd
401
402 NULLFREE (cl);
403
404 //decrease cwcache
405 pthread_mutex_lock(&cwcache_lock);
406 struct s_ecm *ecmc;
407 if (cwidx->next) {
408 if (cwidx->next->next) {
409 ecmc=cwidx->next->next;
410 NULLFREE(cwidx->next);
411 cwidx->next=ecmc;
412 } else
413 NULLFREE(cwidx->next);
414 } else {
415 ecmc=cwcache->next;
416 NULLFREE(cwcache);
417 cwcache=ecmc;
418 }
419 pthread_mutex_unlock(&cwcache_lock);
420 //decrease ecmache
421 if (ecmcache->next != NULL) { //keep it at least on one entry big
422 for (ecmc=ecmcache; ecmc->next->next ; ecmc=ecmc->next) ; //find last element
423 if (ecmidx==ecmc->next)
424 ecmidx = ecmcache;
425 NULLFREE(ecmc->next); //free last element
426 }
427}
428
429void cs_exit(int sig)
430{
431 char targetfile[256];
432
433 set_signal_handler(SIGCHLD, 1, SIG_IGN);
434 set_signal_handler(SIGHUP , 1, SIG_IGN);
435 set_signal_handler(SIGPIPE, 1, SIG_IGN);
436
437 if (sig==SIGALRM) {
438 cs_debug("thread %8X: SIGALRM, skipping", pthread_self());
439 return;
440 }
441
442 if (sig && (sig!=SIGQUIT))
443 cs_log("exit with signal %d", sig);
444
445 struct s_client *cl = cur_client();
446
447 switch(cl->typ)
448 {
449 case 'c':
450 cs_statistics(cl);
451 cl->last_caid = 0xFFFF;
452 cl->last_srvid = 0xFFFF;
453 cs_statistics(cl);
454 break;
455
456 case 'm': break;
457 case 'r':
458 // free AES entries allocated memory
459 if(cl->reader->aes_list) {
460 aes_clear_entries(cl->reader);
461 }
462 // close the device
463 reader_device_close(cl->reader);
464 break;
465
466 case 'h':
467 case 's':
468#ifdef CS_LED
469 cs_switch_led(LED1B, LED_OFF);
470 cs_switch_led(LED2, LED_OFF);
471 cs_switch_led(LED3, LED_OFF);
472 cs_switch_led(LED1A, LED_ON);
473#endif
474#ifdef QBOXHD_LED
475 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_FAST);
476 qboxhd_led_blink(QBOXHD_LED_COLOR_RED,QBOXHD_LED_BLINK_FAST);
477 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_FAST);
478 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE,QBOXHD_LED_BLINK_FAST);
479 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_FAST);
480#endif
481
482#ifndef OS_CYGWIN32
483 snprintf(targetfile, 255, "%s%s", get_tmp_dir(), "/oscam.version");
484 if (unlink(targetfile) < 0)
485 cs_log("cannot remove oscam version file %s errno=(%d)", targetfile, errno);
486#endif
487 break;
488 }
489
490 // this is very important - do not remove
491 if (cl->typ != 's') {
492 cs_log("thread %8X ended!", pthread_self());
493 cleanup_thread(cl);
494 //Restore signals before exiting thread
495 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
496 set_signal_handler(SIGHUP , 1, cs_accounts_chk);
497
498 pthread_exit(NULL);
499 return;
500 }
501
502 cs_log("cardserver down");
503 cs_close_log();
504
505 NULLFREE(cl);
506
507 exit(sig); //clears all threads
508}
509
510void cs_reinit_clients()
511{
512 struct s_auth *account;
513
514 struct s_client *cl;
515 for (cl=first_client->next; cl ; cl=cl->next)
516 if( cl->typ == 'c' && cl->usr[0] ) {
517 for (account = cfg->account; (account) ; account = account->next)
518 if (!strcmp(cl->usr, account->usr))
519 break;
520
521 if (account && cl->pcrc == crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), cur_client()->dump), 16)) {
522 cl->grp = account->grp;
523 cl->aureader = account->aureader;
524 cl->autoau = account->autoau;
525 cl->expirationdate = account->expirationdate;
526 cl->allowedtimeframe[0] = account->allowedtimeframe[0];
527 cl->allowedtimeframe[1] = account->allowedtimeframe[1];
528 cl->ncd_keepalive = account->ncd_keepalive;
529 cl->c35_suppresscmd08 = account->c35_suppresscmd08;
530 cl->tosleep = (60*account->tosleep);
531 cl->c35_sleepsend = account->c35_sleepsend;
532 cl->monlvl = account->monlvl;
533 cl->disabled = account->disabled;
534 cl->fchid = account->fchid; // CHID filters
535 cl->cltab = account->cltab; // Class
536
537 // newcamd module dosent like ident reloading
538 if(!cl->ncd_server)
539 cl->ftab = account->ftab; // Ident
540
541 cl->sidtabok = account->sidtabok; // services
542 cl->sidtabno = account->sidtabno; // services
543 cl->failban = account->failban;
544
545 memcpy(&cl->ctab, &account->ctab, sizeof(cl->ctab));
546 memcpy(&cl->ttab, &account->ttab, sizeof(cl->ttab));
547
548#ifdef CS_ANTICASC
549 cl->ac_idx = account->ac_idx;
550 cl->ac_penalty= account->ac_penalty;
551 cl->ac_limit = (account->ac_users * 100 + 80) * cfg->ac_stime;
552#endif
553 } else {
554 if (ph[cl->ctyp].type & MOD_CONN_NET) {
555 cs_debug("client '%s', thread=%8X not found in db (or password changed)", cl->usr, cl->thread);
556 kill_thread(cl);
557 }
558 }
559 }
560}
561
562void cs_debug_level()
563{
564 //switch debuglevel forward one step if not set from outside
565 if(cfg->debuglvl == cs_dblevel) {
566 switch (cs_dblevel) {
567 case 0:
568 cs_dblevel = 1;
569 break;
570 case 64:
571 cs_dblevel = 255;
572 break;
573 case 255:
574 cs_dblevel = 0;
575 break;
576 default:
577 cs_dblevel <<= 1;
578 }
579 } else {
580 cs_dblevel = cfg->debuglvl;
581 }
582
583 cfg->debuglvl = cs_dblevel;
584 cs_log("%sdebug_level=%d", "all", cs_dblevel);
585}
586
587void cs_card_info()
588{
589 uchar dummy[1]={0x00};
590 struct s_client *cl;
591 for (cl=first_client->next; cl ; cl=cl->next)
592 if( cl->typ=='r' && cl->fd_m2c )
593 write_to_pipe(cl->fd_m2c, PIP_ID_CIN, dummy, 1);
594 //kill(client[i].pid, SIGUSR2);
595}
596
597struct s_client * cs_fork(in_addr_t ip) {
598 struct s_client *cl;
599
600 for (cl=first_client; cl->next != NULL; cl=cl->next); //ends with cl on last client
601 cl->next = malloc(sizeof(struct s_client));
602 if (cl->next) {
603 cl = cl->next; //move to next empty slot
604 memset(cl, 0, sizeof(struct s_client));
605 cl->next = NULL;
606 int fdp[2];
607 cl->aureader=NULL;
608 if (pipe(fdp)) {
609 cs_log("Cannot create pipe (errno=%d: %s)", errno, strerror(errno));
610 //cs_exit(1);
611 return NULL;
612 }
613 //client part
614
615 //make_non_blocking(fdp[0]);
616 //make_non_blocking(fdp[1]);
617 cl->cs_ptyp=D_CLIENT;
618 cl->fd_m2c_c = fdp[0]; //store client read fd
619 cl->fd_m2c = fdp[1]; //store client read fd
620 cl->ip=ip;
621
622 //master part
623 cl->stat=1;
624
625 cl->login=cl->last=time((time_t *)0);
626 //increase cwcache
627 pthread_mutex_lock(&cwcache_lock);
628 struct s_ecm *ecmc;
629 for (ecmc=cwcache; ecmc->next ; ecmc=ecmc->next); //ends on last cwcache entry
630 ecmc->next = malloc(sizeof(struct s_ecm));
631 if (ecmc->next)
632 memset(ecmc->next, 0, sizeof(struct s_ecm));
633 pthread_mutex_unlock(&cwcache_lock);
634
635 //increase ecmcache
636 for (ecmc=ecmcache; ecmc->next ; ecmc=ecmc->next); //ends on last ecmcache entry
637 ecmc->next = malloc(sizeof(struct s_ecm));
638 if (ecmc->next)
639 memset(ecmc->next, 0, sizeof(struct s_ecm));
640 } else {
641 cs_log("max connections reached -> reject client %s", cs_inet_ntoa(ip));
642 return NULL;
643 }
644 return(cl);
645}
646
647static void init_signal()
648{
649// for (i=1; i<NSIG; i++)
650// set_signal_handler(i, 3, cs_exit); //not catching all signals simplifies debugging
651 set_signal_handler(SIGINT, 3, cs_exit);
652 set_signal_handler(SIGKILL, 3, cs_exit);
653#ifdef OS_MACOSX
654 set_signal_handler(SIGEMT, 3, cs_exit);
655#else
656 //set_signal_handler(SIGPOLL, 3, cs_exit);
657#endif
658 //set_signal_handler(SIGPROF, 3, cs_exit);
659 set_signal_handler(SIGTERM, 3, cs_exit);
660 //set_signal_handler(SIGVTALRM, 3, cs_exit);
661
662 set_signal_handler(SIGWINCH, 1, SIG_IGN);
663 // set_signal_handler(SIGPIPE , 0, SIG_IGN);
664 set_signal_handler(SIGPIPE , 0, cs_sigpipe);
665 // set_signal_handler(SIGALRM , 0, cs_alarm);
666 set_signal_handler(SIGALRM , 0, cs_master_alarm);
667 // set_signal_handler(SIGCHLD , 1, cs_child_chk);
668 set_signal_handler(SIGHUP , 1, cs_accounts_chk);
669 //set_signal_handler(SIGHUP , 1, cs_sighup);
670 set_signal_handler(SIGUSR1, 1, cs_debug_level);
671 set_signal_handler(SIGUSR2, 1, cs_card_info);
672 set_signal_handler(SIGCONT, 1, SIG_IGN);
673 cs_log("signal handling initialized (type=%s)",
674#ifdef CS_SIGBSD
675 "bsd"
676#else
677 "sysv"
678#endif
679 );
680 return;
681}
682
683static struct s_ecm *generate_cache()
684{
685 int i;
686 struct s_ecm *idx, *cache;
687 cache=idx=malloc(sizeof(struct s_ecm));
688 memset(idx, 0, sizeof(struct s_ecm));
689 for(i=0;i<10;i++) {
690 idx->next=malloc(sizeof(struct s_ecm));
691 idx=idx->next;
692 memset(idx, 0, sizeof(struct s_ecm));
693 }
694 return cache;
695}
696
697static void init_shm()
698{
699 //Generate 5 CW cache entries:
700 cwidx=cwcache=generate_cache();
701
702 //Generate 5 ECM cache entries:
703 ecmidx=ecmcache=generate_cache();
704
705 first_client = malloc(sizeof(struct s_client));
706 if (!first_client) {
707 fprintf(stderr, "Could not allocate memory for master client, exiting...");
708 exit(1);
709 }
710 first_client->next = NULL; //terminate clients list with NULL
711 first_client->login=time((time_t *)0);
712 first_client->ip=cs_inet_addr("127.0.0.1");
713 first_client->typ='s';
714 first_client->aureader=NULL;
715 first_client->thread=pthread_self();
716 if (pthread_setspecific(getclient, first_client)) {
717 fprintf(stderr, "Could not setspecific getclient in master process, exiting...");
718 exit(1);
719 }
720
721
722 // get username master running under
723 struct passwd *pwd;
724 if ((pwd = getpwuid(getuid())) != NULL)
725 strcpy(first_client->usr, pwd->pw_name);
726 else
727 strcpy(first_client->usr, "root");
728
729 pthread_mutex_init(&gethostbyname_lock, NULL);
730 pthread_mutex_init(&cwcache_lock, NULL);
731 pthread_mutex_init(&ecmcache_lock, NULL);
732
733#ifdef CS_LOGHISTORY
734 loghistidx=0;
735 memset(loghist, 0, CS_MAXLOGHIST*CS_LOGHISTSIZE);
736#endif
737}
738
739static int start_listener(struct s_module *ph, int port_idx)
740{
741 int ov=1, timeout, is_udp, i;
742 char ptxt[2][32];
743 //struct hostent *ptrh; /* pointer to a host table entry */
744 struct protoent *ptrp; /* pointer to a protocol table entry */
745 struct sockaddr_in sad; /* structure to hold server's address */
746
747 ptxt[0][0]=ptxt[1][0]='\0';
748 if (!ph->ptab->ports[port_idx].s_port)
749 {
750 cs_log("%s: disabled", ph->desc);
751 return(0);
752 }
753 is_udp=(ph->type==MOD_CONN_UDP);
754
755 memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
756 sad.sin_family = AF_INET; /* set family to Internet */
757 if (!ph->s_ip)
758 ph->s_ip=cfg->srvip;
759 if (ph->s_ip)
760 {
761 sad.sin_addr.s_addr=ph->s_ip;
762 sprintf(ptxt[0], ", ip=%s", inet_ntoa(sad.sin_addr));
763 }
764 else
765 sad.sin_addr.s_addr=INADDR_ANY;
766 timeout=cfg->bindwait;
767 //ph->fd=0;
768 ph->ptab->ports[port_idx].fd = 0;
769
770 if (ph->ptab->ports[port_idx].s_port > 0) /* test for illegal value */
771 sad.sin_port = htons((u_short)ph->ptab->ports[port_idx].s_port);
772 else
773 {
774 cs_log("%s: Bad port %d", ph->desc, ph->ptab->ports[port_idx].s_port);
775 return(0);
776 }
777
778 /* Map transport protocol name to protocol number */
779
780 if( (ptrp=getprotobyname(is_udp ? "udp" : "tcp")) )
781 ov=ptrp->p_proto;
782 else
783 ov=(is_udp) ? 17 : 6; // use defaults on error
784
785 if ((ph->ptab->ports[port_idx].fd=socket(PF_INET,is_udp ? SOCK_DGRAM : SOCK_STREAM, ov))<0)
786 {
787 cs_log("%s: Cannot create socket (errno=%d: %s)", ph->desc, errno, strerror(errno));
788 return(0);
789 }
790
791 ov=1;
792 if (setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&ov, sizeof(ov))<0)
793 {
794 cs_log("%s: setsockopt failed (errno=%d: %s)", ph->desc, errno, strerror(errno));
795 close(ph->ptab->ports[port_idx].fd);
796 return(ph->ptab->ports[port_idx].fd=0);
797 }
798
799#ifdef SO_REUSEPORT
800 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_REUSEPORT, (void *)&ov, sizeof(ov));
801#endif
802
803#ifdef SO_PRIORITY
804 if (cfg->netprio)
805 if (!setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_PRIORITY, (void *)&cfg->netprio, sizeof(ulong)))
806 sprintf(ptxt[1], ", prio=%ld", cfg->netprio);
807#endif
808
809 if( !is_udp )
810 {
811 ulong keep_alive = 1;
812 setsockopt(ph->ptab->ports[port_idx].fd, SOL_SOCKET, SO_KEEPALIVE,
813 (void *)&keep_alive, sizeof(ulong));
814 }
815
816 while (timeout--)
817 {
818 if (bind(ph->ptab->ports[port_idx].fd, (struct sockaddr *)&sad, sizeof (sad))<0)
819 {
820 if (timeout)
821 {
822 cs_log("%s: Bind request failed, waiting another %d seconds",
823 ph->desc, timeout);
824 cs_sleepms(1000);
825 }
826 else
827 {
828 cs_log("%s: Bind request failed, giving up", ph->desc);
829 close(ph->ptab->ports[port_idx].fd);
830 return(ph->ptab->ports[port_idx].fd=0);
831 }
832 }
833 else timeout=0;
834 }
835
836 if (!is_udp)
837 if (listen(ph->ptab->ports[port_idx].fd, CS_QLEN)<0)
838 {
839 cs_log("%s: Cannot start listen mode (errno=%d: %s)", ph->desc, errno, strerror(errno));
840 close(ph->ptab->ports[port_idx].fd);
841 return(ph->ptab->ports[port_idx].fd=0);
842 }
843
844 cs_log("%s: initialized (fd=%d, port=%d%s%s%s)",
845 ph->desc, ph->ptab->ports[port_idx].fd,
846 ph->ptab->ports[port_idx].s_port,
847 ptxt[0], ptxt[1], ph->logtxt ? ph->logtxt : "");
848
849 for( i=0; i<ph->ptab->ports[port_idx].ftab.nfilts; i++ ) {
850 int j;
851 cs_log("CAID: %04X", ph->ptab->ports[port_idx].ftab.filts[i].caid );
852 for( j=0; j<ph->ptab->ports[port_idx].ftab.filts[i].nprids; j++ )
853 cs_log("provid #%d: %06X", j, ph->ptab->ports[port_idx].ftab.filts[i].prids[j]);
854 }
855 return(ph->ptab->ports[port_idx].fd);
856}
857
858int cs_user_resolve(struct s_auth *account)
859{
860 struct hostent *rht;
861 struct sockaddr_in udp_sa;
862 int result=0;
863 if (account->dyndns[0])
864 {
865 pthread_mutex_lock(&gethostbyname_lock);
866 in_addr_t lastip = account->dynip;
867 //Resolve with gethostbyname:
868 if (cfg->resolve_gethostbyname) {
869 rht = gethostbyname((char*)account->dyndns);
870 if (!rht)
871 cs_log("can't resolve %s", account->dyndns);
872 else {
873 memcpy(&udp_sa.sin_addr, rht->h_addr, sizeof(udp_sa.sin_addr));
874 account->dynip=cs_inet_order(udp_sa.sin_addr.s_addr);
875 result=1;
876 }
877 }
878 else { //Resolve with getaddrinfo:
879 struct addrinfo hints, *res = NULL;
880 memset(&hints, 0, sizeof(hints));
881 hints.ai_socktype = SOCK_STREAM;
882 hints.ai_family = AF_INET;
883 hints.ai_protocol = IPPROTO_TCP;
884
885 int err = getaddrinfo((const char*)account->dyndns, NULL, &hints, &res);
886 if (err != 0 || !res || !res->ai_addr) {
887 cs_log("can't resolve %s, error: %s", account->dyndns, err ? gai_strerror(err) : "unknown");
888 }
889 else {
890 account->dynip=cs_inet_order(((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr);
891 result=1;
892 }
893 if (res) freeaddrinfo(res);
894 }
895 if (lastip != account->dynip) {
896 uchar *ip = (uchar*) &account->dynip;
897 cs_log("%s: resolved ip=%d.%d.%d.%d", (char*)account->dyndns, ip[3], ip[2], ip[1], ip[0]);
898 }
899 pthread_mutex_unlock(&gethostbyname_lock);
900 }
901 if (!result)
902 account->dynip=0;
903 return result;
904}
905#if defined(CS_ANTICASC) || defined(WEBIF)
906static void start_thread(void * startroutine, char * nameroutine) {
907 pthread_t temp;
908 pthread_attr_t attr;
909 pthread_attr_init(&attr);
910#ifndef TUXBOX
911 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
912#endif
913 if (pthread_create(&temp, &attr, startroutine, NULL))
914 cs_log("ERROR: can't create %s thread", nameroutine);
915 else {
916 cs_log("%s thread started", nameroutine);
917 pthread_detach(temp);
918 }
919 pthread_attr_destroy(&attr);
920}
921#endif
922void kill_thread(struct s_client *cl) { //cs_exit is used to let thread kill itself, this routine is for a thread to kill other thread
923
924 if (!cl) return;
925 if (pthread_equal(cl->thread, pthread_self())) return; //cant kill yourself
926
927 pthread_cancel(cl->thread);
928 cs_log("thread %8X killed!", cl->thread);
929 cleanup_thread(cl); //FIXME what about when cancellation was not granted immediately?
930 return;
931}
932
933#ifdef CS_ANTICASC
934void start_anticascader()
935{
936 struct s_client * cl = cs_fork(first_client->ip);
937 if (cl == NULL) return;
938 cl->thread = pthread_self();
939 pthread_setspecific(getclient, cl);
940 strcpy(cl->usr, first_client->usr);
941 cl->typ = 'a';
942
943 set_signal_handler(SIGHUP, 1, ac_init_stat);
944 ac_init_stat();
945 while(1)
946 {
947 cs_sleepms(1000); //FIXME this is a cpu-killer!
948 ac_do_stat();
949 }
950}
951#endif
952
953void restart_cardreader(struct s_reader *rdr, int restart) {
954 int i;
955 if (restart) //kill old thread, even when .deleted flag is set
956 kill_thread(rdr->client);
957
958 rdr->tcp_connected = 0;
959 rdr->card_status = NO_CARD;
960 rdr->tcp_block_delay = 100;
961 cs_ftime(&rdr->tcp_block_connect_till);
962
963 if (rdr->device[0] && (rdr->typ & R_IS_CASCADING)) {
964 for (i=0; i<CS_MAX_MOD; i++)
965 if (ph[i].num && rdr->typ==ph[i].num)
966 rdr->ph=ph[i];
967
968 if (!rdr->ph.num) {
969 cs_log("Protocol Support missing. (typ=%d)", rdr->typ);
970 return;
971 }
972 cs_debug("reader %s protocol: %s", rdr->label, rdr->ph.desc);
973 }
974
975 if (rdr->enable == 0)
976 return;
977
978 if ((rdr->device[0]) && (!rdr->deleted)) {
979 if (restart) {
980 cs_log("restarting reader %s", rdr->label);
981 }
982
983 struct s_client * cl = cs_fork(first_client->ip);
984 if (cl == NULL) return;
985
986
987 rdr->fd=cl->fd_m2c;
988 cl->reader=rdr;
989 cs_log("creating thread for device %s slot %i", rdr->device, rdr->slot);
990
991 cl->sidtabok=rdr->sidtabok;
992 cl->sidtabno=rdr->sidtabno;
993
994 rdr->client=cl;
995
996 cl->typ='r';
997 //client[i].ctyp=99;
998 pthread_attr_t attr;
999 pthread_attr_init(&attr);
1000#if !defined(TUXBOX) && !defined(HAVE_PCSC)
1001 /* pcsc doesn't like this either; segfaults on x86, x86_64 */
1002 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
1003#endif
1004 pthread_create(&cl->thread, &attr, start_cardreader, (void *)rdr);
1005 pthread_detach(cl->thread);
1006 pthread_attr_destroy(&attr);
1007 }
1008}
1009
1010static void init_cardreader() {
1011 struct s_reader *rdr;
1012 for (rdr=first_reader; rdr ; rdr=rdr->next)
1013 if (rdr->device[0])
1014 restart_cardreader(rdr, 0);
1015}
1016
1017static void cs_fake_client(struct s_client *client, char *usr, int uniq, in_addr_t ip)
1018{
1019 /* Uniq = 1: only one connection per user
1020 *
1021 * Uniq = 2: set (new connected) user only to fake if source
1022 * ip is different (e.g. for newcamd clients with
1023 * different CAID's -> Ports)
1024 *
1025 * Uniq = 3: only one connection per user, but only the last
1026 * login will survive (old mpcs behavior)
1027 *
1028 * Uniq = 4: set user only to fake if source ip is
1029 * different, but only the last login will survive
1030 */
1031
1032 struct s_client *cl;
1033 for (cl=first_client->next; cl ; cl=cl->next)
1034 {
1035 if ((cl->typ == 'c') && !cl->dup && !strcmp(cl->usr, usr)
1036 && (uniq < 5) && ((uniq % 2) || (cl->ip != ip)))
1037 {
1038 if (uniq == 3 || uniq == 4)
1039 {
1040 cl->dup = 1;
1041 cl->aureader = NULL;
1042 cs_log("client(%8X) duplicate user '%s' from %s set to fake (uniq=%d)", cl->thread, usr, cs_inet_ntoa(ip), uniq);
1043 }
1044 else
1045 {
1046 client->dup = 1;
1047 client->aureader = NULL;
1048 cs_log("client(%8X) duplicate user '%s' from %s set to fake (uniq=%d)", pthread_self(), usr, cs_inet_ntoa(ip), uniq);
1049 break;
1050 }
1051
1052 }
1053 }
1054
1055}
1056
1057int cs_auth_client(struct s_client * client, struct s_auth *account, const char *e_txt)
1058{
1059 int rc=0;
1060 char buf[32];
1061 char *t_crypt="encrypted";
1062 char *t_plain="plain";
1063 char *t_grant=" granted";
1064 char *t_reject=" rejected";
1065 char *t_msg[]= { buf, "invalid access", "invalid ip", "unknown reason" };
1066 memset(&client->grp, 0xff, sizeof(uint64));
1067 //client->grp=0xffffffffffffff;
1068 client->aureader=NULL;
1069 switch((long)account)
1070 {
1071#ifdef CS_WITH_GBOX
1072 case -2: // gbx-dummy
1073 client->dup=0;
1074 break;
1075#endif
1076 case 0: // reject access
1077 rc=1;
1078 cs_add_violation((uint)client->ip);
1079 cs_log("%s %s-client %s%s (%s)",
1080 client->crypted ? t_crypt : t_plain,
1081 ph[client->ctyp].desc,
1082 client->ip ? cs_inet_ntoa(client->ip) : "",
1083 client->ip ? t_reject : t_reject+1,
1084 e_txt ? e_txt : t_msg[rc]);
1085 break;
1086 default: // grant/check access
1087 if (client->ip && account->dyndns[0]) {
1088 if (cfg->clientdyndns) {
1089 if (client->ip != account->dynip)
1090 cs_user_resolve(account);
1091 if (client->ip != account->dynip) {
1092 cs_add_violation((uint)client->ip);
1093 rc=2;
1094 }
1095 }
1096 else
1097 cs_log("Warning: clientdyndns disabled in config. Enable clientdyndns to use hostname restrictions");
1098 }
1099
1100 if (!rc)
1101 {
1102 client->dup=0;
1103 if (client->typ=='c')
1104 {
1105 client->last_caid = 0xFFFE;
1106 client->last_srvid = 0xFFFE;
1107 client->expirationdate = account->expirationdate;
1108 client->disabled = account->disabled;
1109 client->allowedtimeframe[0] = account->allowedtimeframe[0];
1110 client->allowedtimeframe[1] = account->allowedtimeframe[1];
1111 client->failban = account->failban;
1112 client->c35_suppresscmd08 = account->c35_suppresscmd08;
1113 client->ncd_keepalive = account->ncd_keepalive;
1114 client->grp = account->grp;
1115 client->aureader = account->aureader;
1116 client->autoau = account->autoau;
1117 client->tosleep = (60*account->tosleep);
1118 client->c35_sleepsend = account->c35_sleepsend;
1119 memcpy(&client->ctab, &account->ctab, sizeof(client->ctab));
1120 if (account->uniq)
1121 cs_fake_client(client, account->usr, account->uniq, client->ip);
1122 client->ftab = account->ftab; // IDENT filter
1123 client->cltab = account->cltab; // CLASS filter
1124 client->fchid = account->fchid; // CHID filter
1125 client->sidtabok= account->sidtabok; // services
1126 client->sidtabno= account->sidtabno; // services
1127 client->pcrc = crc32(0L, MD5((uchar *)account->pwd, strlen(account->pwd), client->dump), 16);
1128 memcpy(&client->ttab, &account->ttab, sizeof(client->ttab));
1129#ifdef CS_ANTICASC
1130 ac_init_client(account);
1131#endif
1132 }
1133 }
1134 client->monlvl=account->monlvl;
1135 strcpy(client->usr, account->usr);
1136 case -1: // anonymous grant access
1137 if (rc)
1138 t_grant=t_reject;
1139 else
1140 if (client->typ=='m')
1141 sprintf(t_msg[0], "lvl=%d", client->monlvl);
1142 else
1143 if(client->autoau)
1144 if(client->ncd_server)
1145 {
1146 struct s_reader *rdr;
1147 for (rdr=first_reader; rdr ; rdr=rdr->next)
1148 if(rdr->caid[0]==cfg->ncd_ptab.ports[client->port_idx].ftab.filts[0].caid) {
1149 client->aureader=rdr;
1150 break;
1151 }
1152 if(!client->aureader)
1153 sprintf(t_msg[0], "au(auto)=0"); //FIXME dont think this is correct, but this was old behaviour
1154 else
1155 sprintf(t_msg[0], "au(auto)=%s", client->aureader->label);
1156 }
1157 else
1158 sprintf(t_msg[0], "au=auto");
1159 else
1160 if(!client->aureader)
1161 sprintf(t_msg[0], "au(auto)=0"); //FIXME dont think this is correct, but this was old behaviour
1162 else
1163 sprintf(t_msg[0], "au=%s", client->aureader->label);
1164
1165 if(client->ncd_server)
1166 {
1167 cs_log("%s %s:%d-client %s%s (%s, %s)",
1168 client->crypted ? t_crypt : t_plain,
1169 e_txt ? e_txt : ph[client->ctyp].desc,
1170 cfg->ncd_ptab.ports[client->port_idx].s_port,
1171 client->ip ? cs_inet_ntoa(client->ip) : "",
1172 client->ip ? t_grant : t_grant+1,
1173 username(client), t_msg[rc]);
1174 }
1175 else
1176 {
1177 cs_log("%s %s-client %s%s (%s, %s)",
1178 client->crypted ? t_crypt : t_plain,
1179 e_txt ? e_txt : ph[client->ctyp].desc,
1180 client->ip ? cs_inet_ntoa(client->ip) : "",
1181 client->ip ? t_grant : t_grant+1,
1182 username(client), t_msg[rc]);
1183 }
1184
1185 break;
1186 }
1187 return(rc);
1188}
1189
1190void cs_disconnect_client(struct s_client * client)
1191{
1192 char buf[32]={0};
1193 if (client->ip)
1194 sprintf(buf, " from %s", cs_inet_ntoa(client->ip));
1195 cs_log("%s disconnected %s", username(client), buf);
1196 cs_exit(0);
1197}
1198
1199static void store_ecm(ECM_REQUEST *er, uint64 grp)
1200{
1201 if (ecmidx->next)
1202 ecmidx=ecmidx->next;
1203 else
1204 ecmidx=ecmcache;
1205 memcpy(ecmidx->ecmd5, er->ecmd5, CS_ECMSTORESIZE);
1206 ecmidx->caid = er->caid;
1207 ecmidx->grp = grp;
1208 ecmidx->reader = er->selected_reader;
1209}
1210
1211/**
1212 * ecm cache
1213 **/
1214static int check_and_store_ecmcache(ECM_REQUEST *er, uint64 grp)
1215{
1216 struct s_ecm *ecmc;
1217 pthread_mutex_lock(&ecmcache_lock);
1218 for (ecmc=ecmcache; ecmc ; ecmc=ecmc->next)
1219 if ((grp & ecmc->grp) &&
1220 ecmc->caid==er->caid &&
1221 (!memcmp(ecmc->ecmd5, er->ecmd5, CS_ECMSTORESIZE)))
1222 {
1223 er->rc = 99;
1224 pthread_mutex_unlock(&ecmcache_lock);
1225 return(1);
1226 }
1227 store_ecm(er, grp); //Only ECM, no CW!
1228 pthread_mutex_unlock(&ecmcache_lock);
1229 return(0);
1230}
1231
1232/**
1233 * cache 1: client-invoked
1234 * returns found ecm task index
1235 **/
1236static int check_cwcache1(ECM_REQUEST *er, uint64 grp)
1237{
1238 //cs_ddump(ecmd5, CS_ECMSTORESIZE, "ECM search");
1239 //cs_log("cache1 CHECK: grp=%lX", grp);
1240 struct s_ecm *ecmc;
1241 int count=0;
1242
1243 ushort lc=0, *lp;
1244 if (cs_dblevel) {
1245 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1246 lc^=*lp;
1247 }
1248
1249 pthread_mutex_lock(&cwcache_lock);
1250 for (ecmc=cwcache; ecmc ; ecmc=ecmc->next, count++) {
1251 if (memcmp(ecmc->ecmd5, er->ecmd5, CS_ECMSTORESIZE))
1252 continue;
1253
1254 cs_debug_mask(D_TRACE, "cache: ecm %04X found: caid=%04X grp=%lld cgrp=%lld", lc, ecmc->caid, grp, ecmc->grp);
1255
1256 if (!(grp & ecmc->grp))
1257 continue;
1258
1259 if (ecmc->caid != er->caid)
1260 continue;
1261
1262 cs_debug_mask(D_TRACE, "cache: found count=%d", count);
1263 memcpy(er->cw, ecmc->cw, 16);
1264 er->selected_reader = ecmc->reader;
1265 pthread_mutex_unlock(&cwcache_lock);
1266 return 1;
1267 }
1268 pthread_mutex_unlock(&cwcache_lock);
1269 cs_debug_mask(D_TRACE, "cache: %04X not found count=%d", lc, count);
1270 return 0;
1271}
1272
1273/**
1274 * cache 2: reader-invoked
1275 * returns 1 if found in cache. cw is copied to er
1276 **/
1277int check_cwcache2(ECM_REQUEST *er, uint64 grp)
1278{
1279 struct s_reader *save = er->selected_reader;
1280 int rc = check_cwcache1(er, grp);
1281 er->selected_reader = save;
1282 return rc;
1283}
1284
1285
1286static void store_cw(ECM_REQUEST *er, uint64 grp)
1287{
1288#ifdef CS_WITH_DOUBLECHECK
1289 if (cfg->double_check && er->checked < 2)
1290 return;
1291#endif
1292 pthread_mutex_lock(&cwcache_lock);
1293 if (cwidx->next)
1294 cwidx=cwidx->next;
1295 else
1296 cwidx=cwcache;
1297 //cs_log("store ecm from reader %d", er->selected_reader);
1298 memcpy(cwidx->ecmd5, er->ecmd5, CS_ECMSTORESIZE);
1299 memcpy(cwidx->cw, er->cw, 16);
1300 cwidx->caid = er->caid;
1301 cwidx->grp = grp;
1302 cwidx->reader = er->selected_reader;
1303
1304 if (cs_dblevel) {
1305 ushort lc, *lp;
1306 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1307 lc^=*lp;
1308 cs_debug_mask(D_TRACE, "store_cw: ecm=%04X grp=%lld", lc, grp);
1309 }
1310 //cs_ddump(cwcache[*cwidx].ecmd5, CS_ECMSTORESIZE, "ECM stored (idx=%d)", *cwidx);
1311 pthread_mutex_unlock(&cwcache_lock);
1312}
1313
1314// only for debug
1315static struct s_client * get_thread_by_pipefd(int fd)
1316{
1317 struct s_client *cl;
1318 for (cl=first_client->next; cl ; cl=cl->next)
1319 if (fd==cl->fd_m2c || fd==cl->fd_m2c_c)
1320 return cl;
1321 return first_client; //master process
1322}
1323
1324/*
1325 * write_to_pipe():
1326 * write all kind of data to pipe specified by fd
1327 */
1328int write_to_pipe(int fd, int id, uchar *data, int n)
1329{
1330 if (!fd) {
1331 cs_log("write_to_pipe: fd==0 id: %d", id);
1332 return -1;
1333 }
1334
1335 cs_debug("write to pipe %d (%s) thread: %8X to %8X", fd, PIP_ID_TXT[id], pthread_self(), get_thread_by_pipefd(fd)->thread);
1336
1337 uchar buf[3+sizeof(void*)];
1338
1339 // fixme
1340 // copy data to allocated memory
1341 // needed for compatibility
1342 // need to be freed after read_from_pipe
1343 void *d = malloc(n);
1344 memcpy(d, data, n);
1345
1346 if ((id<0) || (id>PIP_ID_MAX))
1347 return(PIP_ID_ERR);
1348
1349 memcpy(buf, PIP_ID_TXT[id], 3);
1350 memcpy(buf+3, &d, sizeof(void*));
1351
1352 n=3+sizeof(void*);
1353
1354 return(write(fd, buf, n));
1355}
1356
1357
1358/*
1359 * read_from_pipe():
1360 * read all kind of data from pipe specified by fd
1361 * special-flag redir: if set AND data is ECM: this will redirected to appr. client
1362 */
1363int read_from_pipe(int fd, uchar **data, int redir)
1364{
1365 int rc;
1366 long hdr=0;
1367 uchar buf[3+sizeof(void*)];
1368 memset(buf, 0, sizeof(buf));
1369
1370 redir=redir;
1371 *data=(uchar *)0;
1372 rc=PIP_ID_NUL;
1373
1374 if (bytes_available(fd)) {
1375 if (read(fd, buf, sizeof(buf))==sizeof(buf)) {
1376 memcpy(&hdr, buf+3, sizeof(void*));
1377 } else {
1378 cs_log("WARNING: pipe header to small !");
1379 return PIP_ID_ERR;
1380 }
1381 } else {
1382 cs_log("!bytes_available(fd)");
1383 return PIP_ID_NUL;
1384 }
1385
1386 uchar id[4];
1387 memcpy(id, buf, 3);
1388 id[3]='\0';
1389
1390 cs_debug("read from pipe %d (%s) thread: %8X", fd, id, (unsigned int)pthread_self());
1391
1392 int l;
1393 for (l=0; (rc<0) && (PIP_ID_TXT[l]); l++)
1394 if (!memcmp(buf, PIP_ID_TXT[l], 3))
1395 rc=l;
1396
1397 if (rc<0) {
1398 cs_log("WARNING: pipe garbage from pipe %i", fd);
1399 return PIP_ID_ERR;
1400 }
1401
1402 *data = (void*)hdr;
1403
1404 return(rc);
1405}
1406
1407/*
1408 * write_ecm_request():
1409 */
1410int write_ecm_request(int fd, ECM_REQUEST *er)
1411{
1412 return(write_to_pipe(fd, PIP_ID_ECM, (uchar *) er, sizeof(ECM_REQUEST)));
1413}
1414
1415/*
1416 * This function writes the current CW from ECM struct to a cwl file.
1417 * The filename is re-calculated and file re-opened every time.
1418 * This will consume a bit cpu time, but nothing has to be stored between
1419 * each call. If not file exists, a header is prepended
1420 */
1421void logCWtoFile(ECM_REQUEST *er)
1422{
1423 FILE *pfCWL;
1424 char srvname[128];
1425 /* %s / %s _I %04X _ %s .cwl */
1426 char buf[256 + sizeof(srvname)];
1427 char date[7];
1428 unsigned char i, parity, writeheader = 0;
1429 time_t t;
1430 struct tm *timeinfo;
1431 struct s_srvid *this;
1432
1433 /*
1434 * search service name for that id and change characters
1435 * causing problems in file name
1436 */
1437 srvname[0] = 0;
1438 for (this=cfg->srvid; this; this = this->next) {
1439 if (this->srvid == er->srvid) {
1440 cs_strncpy(srvname, this->name, sizeof(srvname));
1441 srvname[sizeof(srvname)-1] = 0;
1442 for (i = 0; srvname[i]; i++)
1443 if (srvname[i] == ' ') srvname[i] = '_';
1444 break;
1445 }
1446 }
1447
1448 /* calc log file name */
1449 time(&t);
1450 timeinfo = localtime(&t);
1451 strftime(date, sizeof(date), "%Y%m%d", timeinfo);
1452 sprintf(buf, "%s/%s_I%04X_%s.cwl", cfg->cwlogdir, date, er->srvid, srvname);
1453
1454 /* open failed, assuming file does not exist, yet */
1455 if((pfCWL = fopen(buf, "r")) == NULL) {
1456 writeheader = 1;
1457 } else {
1458 /* we need to close the file if it was opened correctly */
1459 fclose(pfCWL);
1460 }
1461
1462 if ((pfCWL = fopen(buf, "a+")) == NULL) {
1463 /* maybe this fails because the subdir does not exist. Is there a common function to create it?
1464 for the moment do not print to log on every ecm
1465 cs_log(""error opening cw logfile for writing: %s (errno %d)", buf, errno); */
1466 return;
1467 }
1468 if (writeheader) {
1469 /* no global macro for cardserver name :( */
1470 fprintf(pfCWL, "# OSCam cardserver v%s - http://streamboard.gmc.to:8001/oscam/wiki\n", CS_VERSION_X);
1471 fprintf(pfCWL, "# control word log file for use with tsdec offline decrypter\n");
1472 strftime(buf, sizeof(buf),"DATE %Y-%m-%d, TIME %H:%M:%S, TZ %Z\n", timeinfo);
1473 fprintf(pfCWL, "# %s", buf);
1474 fprintf(pfCWL, "# CAID 0x%04X, SID 0x%04X, SERVICE \"%s\"\n", er->caid, er->srvid, srvname);
1475 }
1476
1477 parity = er->ecm[0]&1;
1478 fprintf(pfCWL, "%d ", parity);
1479 for (i = parity * 8; i < 8 + parity * 8; i++)
1480 fprintf(pfCWL, "%02X ", er->cw[i]);
1481 /* better use incoming time er->tps rather than current time? */
1482 strftime(buf,sizeof(buf),"%H:%M:%S\n", timeinfo);
1483 fprintf(pfCWL, "# %s", buf);
1484 fflush(pfCWL);
1485 fclose(pfCWL);
1486}
1487
1488/**
1489 * distributes found ecm-request to all clients with rc=99
1490 **/
1491void distribute_ecm(ECM_REQUEST *er)
1492{
1493 struct s_client *cl;
1494 ECM_REQUEST *ecm;
1495 int n, i;
1496 if (er->rc==1) //found converted to cache...
1497 er->rc = 2; //cache
1498
1499 for (cl=first_client->next; cl ; cl=cl->next) {
1500 if (cl->fd_m2c && cl->typ=='c' && cl->ecmtask && (er->selected_reader->grp & cl->grp)) {
1501
1502 n=(ph[cl->ctyp].multi)?CS_MAXPENDING:1;
1503 for (i=0; i<n; i++) {
1504 ecm = &cl->ecmtask[i];
1505 if (ecm->rc == 99 && ecm->ocaid==er->ocaid && memcmp(ecm->ecmd5, er->ecmd5, CS_ECMSTORESIZE)==0) {
1506 er->cpti = ecm->cpti;
1507 //cs_log("distribute %04X:%06X:%04X cpti %d to client %s", ecm->caid, ecm->prid, ecm->srvid, ecm->cpti, username(cl));
1508 write_ecm_request(cl->fd_m2c, er);
1509 }
1510 //else if (ecm->rc == 99)
1511 // cs_log("NO-distribute %04X:%06X:%04X cpti %d to client %s", ecm->caid, ecm->prid, ecm->srvid, ecm->cpti, username(cl));
1512 }
1513 }
1514 }
1515}
1516
1517
1518int write_ecm_answer(struct s_reader * reader, ECM_REQUEST *er)
1519{
1520 int i;
1521 uchar c;
1522 for (i=0; i<16; i+=4)
1523 {
1524 c=((er->cw[i]+er->cw[i+1]+er->cw[i+2]) & 0xff);
1525 if (er->cw[i+3]!=c)
1526 {
1527 cs_debug("notice: changed dcw checksum byte cw[%i] from %02x to %02x", i+3, er->cw[i+3],c);
1528 er->cw[i+3]=c;
1529 }
1530 }
1531
1532 er->selected_reader=reader;
1533//cs_log("answer from reader %d (rc=%d)", er->selected_reader, er->rc);
1534 er->caid=er->ocaid;
1535
1536#ifdef CS_WITH_GBOX
1537 if (er->rc==1||(er->gbxRidx&&er->rc==0)) {
1538#else
1539 if (er->rc==1) {
1540#endif
1541 store_cw(er, reader->grp);
1542
1543 /* CWL logging only if cwlogdir is set in config */
1544 if (cfg->cwlogdir != NULL)
1545 logCWtoFile(er);
1546 }
1547
1548 int res=0;
1549 if( er->client && er->client->fd_m2c ) {
1550 //Wie got an ECM (or nok). Now we should check for another clients waiting for it:
1551 res = write_ecm_request(er->client->fd_m2c, er);
1552 //return(write_ecm_request(first_client->fd_m2c, er)); //does this ever happen? Schlocke: should never happen!
1553 }
1554 distribute_ecm(er);
1555
1556 return res;
1557}
1558
1559 /*
1560static int cs_read_timer(int fd, uchar *buf, int l, int msec)
1561{
1562 struct timeval tv;
1563 fd_set fds;
1564 int rc;
1565
1566 if (!fd) return(-1);
1567 tv.tv_sec = msec / 1000;
1568 tv.tv_usec = (msec % 1000) * 1000;
1569 FD_ZERO(&fds);
1570 FD_SET(cur_client()->pfd, &fds);
1571
1572 select(fd+1, &fds, 0, 0, &tv);
1573
1574 rc=0;
1575 if (FD_ISSET(cur_client()->pfd, &fds))
1576 if (!(rc=read(fd, buf, l)))
1577 rc=-1;
1578
1579 return(rc);
1580}*/
1581
1582ECM_REQUEST *get_ecmtask()
1583{
1584 int i, n;
1585 ECM_REQUEST *er=0;
1586 struct s_client *cl = cur_client();
1587
1588 if (!cl->ecmtask)
1589 {
1590 n=(ph[cl->ctyp].multi)?CS_MAXPENDING:1;
1591 if( (cl->ecmtask=(ECM_REQUEST *)malloc(n*sizeof(ECM_REQUEST))) )
1592 memset(cl->ecmtask, 0, n*sizeof(ECM_REQUEST));
1593 }
1594
1595 n=(-1);
1596 if (!cl->ecmtask)
1597 {
1598 cs_log("Cannot allocate memory (errno=%d)", errno);
1599 n=(-2);
1600 }
1601 else
1602 if (ph[cl->ctyp].multi)
1603 {
1604 for (i=0; (n<0) && (i<CS_MAXPENDING); i++)
1605 if (cl->ecmtask[i].rc<99)
1606 er=&cl->ecmtask[n=i];
1607 }
1608 else
1609 er=&cl->ecmtask[n=0];
1610
1611 if (n<0)
1612 cs_log("WARNING: ecm pending table overflow !");
1613 else
1614 {
1615 memset(er, 0, sizeof(ECM_REQUEST));
1616 er->rc=100;
1617 er->cpti=n;
1618 er->client=cl;
1619 cs_ftime(&er->tps);
1620 }
1621 return(er);
1622}
1623
1624static void send_reader_stat(struct s_reader *rdr, ECM_REQUEST *er, int rc)
1625{
1626 if (!cfg->lb_mode || rc == 100)
1627 return;
1628 struct timeb tpe;
1629 cs_ftime(&tpe);
1630 int time = 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm;
1631
1632 add_stat(rdr, er->caid, er->prid, er->srvid, time, rc);
1633}
1634
1635// rc codes:
1636// 0 = found
1637// 1 = cache1
1638// 2 = cache2
1639// 3 = emu
1640// 4 = not found
1641// 5 = timeout
1642// 6 = sleeping
1643// 7 = fake
1644// 8 = invalid
1645// 9 = corrupt
1646// 10= no card
1647// 11= expdate
1648// 12= disabled
1649// 13= stopped
1650// 100=unhandled
1651
1652int send_dcw(struct s_client * client, ECM_REQUEST *er)
1653{
1654 static const char *stxt[]={"found", "cache1", "cache2", "emu",
1655 "not found", "timeout", "sleeping",
1656 "fake", "invalid", "corrupt", "no card", "expdate", "disabled", "stopped"};
1657 static const char *stxtEx[]={"", "group", "caid", "ident", "class", "chid", "queue", "peer"};
1658 static const char *stxtWh[]={"", "user ", "reader ", "server ", "lserver "};
1659 char sby[32]="", sreason[32]="", schaninfo[32]="";
1660 char erEx[32]="";
1661 char uname[38]="";
1662 struct timeb tpe;
1663 ushort lc, *lp;
1664 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
1665 lc^=*lp;
1666
1667#ifdef CS_WITH_GBOX
1668 if(er->gbxFrom)
1669 snprintf(uname,sizeof(uname)-1, "%s(%04X)", username(client), er->gbxFrom);
1670 else
1671#endif
1672 snprintf(uname,sizeof(uname)-1, "%s", username(client));
1673 if (er->rc==0)
1674 {
1675#ifdef CS_WITH_GBOX
1676 if(er->selected_reader->typ==R_GBOX)
1677 snprintf(sby, sizeof(sby)-1, " by %s(%04X)", er->reader0->label,er->gbxCWFrom);
1678 else
1679#endif
1680 // add marker to reader if ECM_REQUEST was betatunneled
1681 if(er->btun)
1682 snprintf(sby, sizeof(sby)-1, " by %s(btun)", er->selected_reader->label);
1683 else
1684 snprintf(sby, sizeof(sby)-1, " by %s", er->selected_reader->label);
1685 }
1686 if (er->rc<4) er->rcEx=0;
1687 if (er->rcEx)
1688 snprintf(erEx, sizeof(erEx)-1, "rejected %s%s", stxtWh[er->rcEx>>4],
1689 stxtEx[er->rcEx&0xf]);
1690
1691 if(cfg->mon_appendchaninfo)
1692 snprintf(schaninfo, sizeof(schaninfo)-1, " - %s", get_servicename(er->srvid, er->caid));
1693
1694 if(er->msglog[0])
1695 snprintf(sreason, sizeof(sreason)-1, " (%s)", er->msglog);
1696
1697 cs_ftime(&tpe);
1698 client->cwlastresptime = 1000*(tpe.time-er->tps.time)+tpe.millitm-er->tps.millitm;
1699
1700#ifdef CS_LED
1701 if(!er->rc) cs_switch_led(LED2, LED_BLINK_OFF);
1702#endif
1703
1704 send_reader_stat(er->selected_reader, er, er->rc);
1705
1706 cs_log("%s (%04X&%06X/%04X/%02X:%04X): %s (%d ms)%s (of %d avail %d)%s%s",
1707 uname, er->caid, er->prid, er->srvid, er->l, lc,
1708 er->rcEx?erEx:stxt[er->rc], client->cwlastresptime, sby, er->reader_count, er->reader_avail, schaninfo, sreason);
1709
1710#ifdef WEBIF
1711 if(er->rc == 0)
1712 snprintf(client->lastreader, sizeof(client->lastreader)-1, "%s", sby);
1713 else if ((er->rc == 1) || (er->rc == 2))
1714 snprintf(client->lastreader, sizeof(client->lastreader)-1, "by %s (cache)", er->selected_reader->label);
1715 else
1716 snprintf(client->lastreader, sizeof(client->lastreader)-1, "%s", stxt[er->rc]);
1717#endif
1718
1719 if(!client->ncd_server && client->autoau && er->rcEx==0 && er->selected_reader)
1720 {
1721 if(client->aureader && er->caid!=client->aureader->caid[0])
1722 {
1723 client->aureader=NULL;
1724 }
1725
1726 struct s_reader *cur = er->selected_reader;
1727
1728 if (cur->typ == R_CCCAM && !cur->caid[0] && !cur->audisabled &&
1729 cur->card_system == get_cardsystem(er->caid) && hexserialset(er->selected_reader))
1730 client->aureader= er->selected_reader;
1731 else if((er->caid == cur->caid[0]) && (!cur->audisabled)) {
1732 client->aureader = er->selected_reader; // First chance - check whether actual reader can AU
1733 } else {
1734 for (cur=first_reader; cur ; cur=cur->next) { //second chance loop through all readers to find an AU reader
1735 if (matching_reader(er, cur)) {
1736 if (cur->typ == R_CCCAM && !cur->caid[0] && !cur->audisabled &&
1737 cur->card_system == get_cardsystem(er->caid) && hexserialset(cur))
1738 {
1739 client->aureader = cur;
1740 break;
1741 }
1742 else if((er->caid == cur->caid[0]) && (er->prid == cur->auprovid) && (!cur->audisabled))
1743 {
1744 client->aureader = cur;
1745 break;
1746 }
1747 }
1748 }
1749 if(!cur) {
1750 client->aureader=NULL;
1751 }
1752 }
1753 //}
1754 }
1755
1756 er->caid = er->ocaid;
1757 switch(er->rc) {
1758 case 0:
1759 case 3:
1760 // 0 - found
1761 // 3 - emu FIXME: obsolete ?
1762 client->cwfound++;
1763 break;
1764
1765 case 1:
1766 case 2:
1767 // 1 - cache1
1768 // 2 - cache2
1769 client->cwcache++;
1770 break;
1771
1772 case 4:
1773 case 9:
1774 case 10:
1775 // 4 - not found
1776 // 9 - corrupt
1777 // 10 - no card
1778 if (er->rcEx)
1779 client->cwignored++;
1780 else
1781 client->cwnot++;
1782 break;
1783
1784 case 5:
1785 // 5 - timeout
1786 client->cwtout++;
1787 break;
1788
1789 default:
1790 client->cwignored++;
1791 }
1792
1793#ifdef CS_ANTICASC
1794 ac_chk(er, 1);
1795#endif
1796
1797 cs_ddump_mask (D_ATR, er->cw, 16, "cw:");
1798 if (er->rc==7) er->rc=0;
1799
1800#ifdef CS_WITH_DOUBLECHECK
1801 if (cfg->double_check && er->rc < 4) {
1802 if (er->checked == 0) {//First CW, save it and wait for next one
1803 er->checked = 1;
1804 er->origin_reader = er->selected_reader;
1805 memcpy(er->cw_checked, er->cw, sizeof(er->cw));
1806 cs_log("DOUBLE CHECK FIRST CW by %s idx %d cpti %d", er->origin_reader->label, er->idx, er->cpti);
1807 }
1808 else if (er->origin_reader != er->selected_reader) { //Second (or third and so on) cw. We have to compare
1809 if (memcmp(er->cw_checked, er->cw, sizeof(er->cw)) == 0) {
1810 er->checked++;
1811 cs_log("DOUBLE CHECKED! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->cpti);
1812 }
1813 else {
1814 cs_log("DOUBLE CHECKED NONMATCHING! %d. CW by %s idx %d cpti %d", er->checked, er->selected_reader->label, er->idx, er->cpti);
1815 }
1816 }
1817
1818 if (er->checked < 2) { //less as two same cw? mark as pending!
1819 er->rc = 100;
1820 return 0;
1821 }
1822
1823 store_cw(er, er->selected_reader->grp); //Store in cache!
1824
1825 }
1826#endif
1827
1828 ph[client->ctyp].send_dcw(client, er);
1829
1830#ifdef QBOXHD_LED
1831 if (er->rc < 4) {
1832 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN, QBOXHD_LED_BLINK_MEDIUM);
1833 } else if (er->rc < 14) {
1834 qboxhd_led_blink(QBOXHD_LED_COLOR_RED, QBOXHD_LED_BLINK_MEDIUM);
1835 }
1836#endif
1837
1838 return 0;
1839}
1840
1841void chk_dcw(struct s_client *cl, ECM_REQUEST *er)
1842{
1843 if (!cl || !cl->ecmtask)
1844 return;
1845
1846 ECM_REQUEST *ert;
1847
1848 //cs_log("dcw check from reader %d for idx %d (rc=%d)", er->selected_reader, er->cpti, er->rc);
1849 ert=&cl->ecmtask[er->cpti];
1850 if (ert->rc<99) {
1851 //cs_debug_mask(D_TRACE, "chk_dcw: already done rc=%d %s", er->rc, er->selected_reader->label);
1852 send_reader_stat(er->selected_reader, er, (er->rc <= 0)?4:0);
1853 return; // already done
1854 }
1855 if( (er->caid!=ert->caid) || memcmp(er->ecmd5, ert->ecmd5, sizeof(er->ecmd5)) )
1856 return; // obsolete
1857
1858 ert->rcEx=er->rcEx;
1859 strcpy(ert->msglog, er->msglog);
1860 ert->selected_reader=er->selected_reader;
1861
1862 // different er->rc codes:
1863 // 0 error
1864 // 1 found
1865 // 2 cache 2
1866 // 3 (emu?)
1867 if (er->rc>0) // found
1868 {
1869 switch(er->rc)
1870 {
1871 case 2:
1872 ert->rc=2;
1873 break;
1874 case 3:
1875 ert->rc=3;
1876 break;
1877 default:
1878 ert->rc=0;
1879 }
1880 ert->rcEx=0;
1881 memcpy(ert->cw , er->cw , sizeof(er->cw));
1882#ifdef CS_WITH_GBOX
1883 ert->gbxCWFrom=er->gbxCWFrom;
1884#endif
1885 } else { // not found (from ONE of the readers !)
1886 int i;
1887 if (er->selected_reader)
1888 ert->matching_rdr[get_ridx(er->selected_reader)]=0; //FIXME one of these two might be superfluous
1889
1890 struct s_reader *rdr;
1891 for (i=0,rdr=first_reader; (ert) && rdr ; rdr=rdr->next, i++) {
1892 if (ert->matching_rdr[i]) { // we have still another chance
1893 ert->selected_reader=0;
1894 ert=(ECM_REQUEST *)0;
1895 }
1896 }
1897
1898 if (ert) ert->rc=4;
1899 else send_reader_stat(er->selected_reader, er, 4);
1900 }
1901 if (ert) send_dcw(cl, ert);
1902 return;
1903}
1904
1905ulong chk_provid(uchar *ecm, ushort caid) {
1906 int i, len, descriptor_length = 0;
1907 ulong provid = 0;
1908
1909 switch(caid >> 8) {
1910 case 0x01:
1911 // seca
1912 provid = b2i(2, ecm+3);
1913 break;
1914
1915 case 0x05:
1916 // viaccess
1917 i = (ecm[4] == 0xD2) ? ecm[5]+2 : 0; // skip d2 nano
1918 if((ecm[5+i] == 3) && ((ecm[4+i] == 0x90) || (ecm[4+i] == 0x40)))
1919 provid = (b2i(3, ecm+6+i) & 0xFFFFF0);
1920
1921 i = (ecm[6] == 0xD2) ? ecm[7]+2 : 0; // skip d2 nano long ecm
1922 if((ecm[7+i] == 7) && ((ecm[6+i] == 0x90) || (ecm[6+i] == 0x40)))
1923 provid = (b2i(3, ecm+8+i) & 0xFFFFF0);
1924
1925 break;
1926
1927 case 0x0D:
1928 // cryptoworks
1929 len = (((ecm[1] & 0xf) << 8) | ecm[2])+3;
1930 for(i=8; i<len; i+=descriptor_length+2) {
1931 descriptor_length = ecm[i+1];
1932 if (ecm[i] == 0x83) {
1933 provid = (ulong)ecm[i+2] & 0xFE;
1934 break;
1935 }
1936 }
1937 break;
1938 }
1939 return(provid);
1940}
1941
1942#ifdef IRDETO_GUESSING
1943void guess_irdeto(ECM_REQUEST *er)
1944{
1945 uchar b3;
1946 int b47;
1947 //ushort chid;
1948 struct s_irdeto_quess *ptr;
1949
1950 b3 = er->ecm[3];
1951 ptr = cfg->itab[b3];
1952 if( !ptr ) {
1953 cs_debug("unknown irdeto byte 3: %02X", b3);
1954 return;
1955 }
1956 b47 = b2i(4, er->ecm+4);
1957 //chid = b2i(2, er->ecm+6);
1958 //cs_debug("ecm: b47=%08X, ptr->b47=%08X, ptr->caid=%04X", b47, ptr->b47, ptr->caid);
1959 while( ptr )
1960 {
1961 if( b47==ptr->b47 )
1962 {
1963 if( er->srvid && (er->srvid!=ptr->sid) )
1964 {
1965 cs_debug("sid mismatched (ecm: %04X, guess: %04X), wrong oscam.ird file?",
1966 er->srvid, ptr->sid);
1967 return;
1968 }
1969 er->caid=ptr->caid;
1970 er->srvid=ptr->sid;
1971 er->chid=(ushort)ptr->b47;
1972// cs_debug("quess_irdeto() found caid=%04X, sid=%04X, chid=%04X",
1973// er->caid, er->srvid, er->chid);
1974 return;
1975 }
1976 ptr=ptr->next;
1977 }
1978}
1979#endif
1980
1981void cs_betatunnel(ECM_REQUEST *er)
1982{
1983 int n;
1984 struct s_client *cl = cur_client();
1985 ulong mask_all = 0xFFFF;
1986 uchar headerN3[10] = {0xc7, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x87, 0x12};
1987 uchar headerN2[10] = {0xc9, 0x00, 0x00, 0x00, 0x01, 0x10, 0x10, 0x00, 0x48, 0x12};
1988 TUNTAB *ttab;
1989 ttab = &cl->ttab;
1990
1991 for (n = 0; (n < CS_MAXTUNTAB); n++) {
1992 if ((er->caid==ttab->bt_caidfrom[n]) && ((er->srvid==ttab->bt_srvid[n]) || (ttab->bt_srvid[n])==mask_all)) {
1993
1994 er->caid = ttab->bt_caidto[n];
1995 er->prid = 0;
1996 er->l = er->ecm[2] + 3;
1997
1998 memmove(er->ecm + 13, er->ecm + 3, er->l - 3);
1999
2000 if (er->l > 0x88) {
2001 memcpy(er->ecm + 3, headerN3, 10);
2002
2003 if (er->ecm[0] == 0x81)
2004 er->ecm[12] += 1;
2005
2006 er->ecm[1]=0x70;
2007 }
2008 else
2009 memcpy(er->ecm + 3, headerN2, 10);
2010
2011 er->l += 10;
2012 er->ecm[2] = er->l - 3;
2013 er->btun = 1;
2014
2015 cl->cwtun++;
2016
2017 cs_debug("ECM converted from: 0x%X to BetaCrypt: 0x%X for service id:0x%X",
2018 ttab->bt_caidfrom[n], ttab->bt_caidto[n], ttab->bt_srvid[n]);
2019 }
2020 }
2021}
2022
2023void guess_cardsystem(ECM_REQUEST *er)
2024{
2025 ushort last_hope=0;
2026
2027 // viaccess - check by provid-search
2028 if( (er->prid=chk_provid(er->ecm, 0x500)) )
2029 er->caid=0x500;
2030
2031 // nagra
2032 // is ecm[1] always 0x30 ?
2033 // is ecm[3] always 0x07 ?
2034 if ((er->ecm[6]==1) && (er->ecm[4]==er->ecm[2]-2))
2035 er->caid=0x1801;
2036
2037 // seca2 - very poor
2038 if ((er->ecm[8]==0x10) && ((er->ecm[9]&0xF1)==1))
2039 last_hope=0x100;
2040
2041 // is cryptoworks, but which caid ?
2042 if ((er->ecm[3]==0x81) && (er->ecm[4]==0xFF) &&
2043 (!er->ecm[5]) && (!er->ecm[6]) && (er->ecm[7]==er->ecm[2]-5))
2044 last_hope=0xd00;
2045
2046#ifdef IRDETO_GUESSING
2047 if (!er->caid && er->ecm[2]==0x31 && er->ecm[0x0b]==0x28)
2048 guess_irdeto(er);
2049#endif
2050
2051 if (!er->caid) // guess by len ..
2052 er->caid=len4caid[er->ecm[2]+3];
2053
2054 if (!er->caid)
2055 er->caid=last_hope;
2056}
2057
2058void request_cw(ECM_REQUEST *er, int flag, int reader_types)
2059{
2060 int i;
2061 if ((reader_types == 0) || (reader_types == 2))
2062 er->level=flag;
2063 flag=(flag)?3:1; // flag specifies with/without fallback-readers
2064 struct s_reader *rdr;
2065
2066 ushort lc=0, *lp;
2067 if (cs_dblevel) {
2068 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
2069 lc^=*lp;
2070 }
2071
2072 for (i=0,rdr=first_reader; rdr ; rdr=rdr->next, i++) {
2073 int status = 0;
2074 switch (reader_types)
2075 {
2076 // network and local cards
2077 default:
2078 case 0:
2079 if (er->matching_rdr[i]&flag){
2080 cs_debug_mask(D_TRACE, "request_cw1 to reader %s ridx=%d fd=%d ecm=%04X", rdr->label, i, rdr->fd, lc);
2081 status = write_ecm_request(rdr->fd, er);
2082 }
2083 break;
2084 // only local cards
2085 case 1:
2086 if (!(rdr->typ & R_IS_NETWORK))
2087 if (er->matching_rdr[i]&flag) {
2088 cs_debug_mask(D_TRACE, "request_cw2 to reader %s ridx=%d fd=%d ecm=%04X", rdr->label, i, rdr->fd, lc);
2089 status = write_ecm_request(rdr->fd, er);
2090 }
2091 break;
2092 // only network
2093 case 2:
2094 //cs_log("request_cw3 ridx=%d fd=%d", i, rdr->fd);
2095 if ((rdr->typ & R_IS_NETWORK))
2096 if (er->matching_rdr[i]&flag) {
2097 cs_debug_mask(D_TRACE, "request_cw3 to reader %s ridx=%d fd=%d ecm=%04X", rdr->label, i, rdr->fd, lc);
2098 status = write_ecm_request(rdr->fd, er);
2099 }
2100 break;
2101 }
2102 if (status == -1) {
2103 cs_log("request_cw() failed on reader %s (%d) errno=%d, %s", rdr->label, i, errno, strerror(errno));
2104 if (rdr->fd) {
2105 rdr->fd_error++;
2106 if (rdr->fd_error > 5) {
2107 rdr->fd_error = 0;
2108 restart_cardreader(rdr, 1); //Schlocke: This restarts the reader!
2109 }
2110 }
2111 }
2112 else
2113 rdr->fd_error = 0;
2114 }
2115}
2116
2117static int update_reader_count(ECM_REQUEST *er) {
2118 int i, m;
2119 struct s_reader *rdr;
2120 for (i=m=0,rdr=first_reader; rdr ; rdr=rdr->next, i++) {
2121 m|=er->matching_rdr[i];
2122 if (er->matching_rdr[i] == 1)
2123 er->reader_count++;
2124 }
2125 return m;
2126}
2127
2128void get_cw(struct s_client * client, ECM_REQUEST *er)
2129{
2130 int i, j, m;
2131 time_t now = time((time_t)0);
2132
2133 client->lastecm = now;
2134
2135 if (!er->caid)
2136 guess_cardsystem(er);
2137
2138 /* Quickfix Area */
2139
2140 if( (er->caid & 0xFF00) == 0x600 && !er->chid )
2141 er->chid = (er->ecm[6]<<8)|er->ecm[7];
2142
2143 // quickfix for 0100:000065
2144 if (er->caid == 0x100 && er->prid == 0x65 && er->srvid == 0)
2145 er->srvid = 0x0642;
2146
2147 // Quickfixes for Opticum/Globo HD9500
2148 // Quickfix for 0500:030300
2149 if (er->caid == 0x500 && er->prid == 0x030300)
2150 er->prid = 0x030600;
2151
2152 // Quickfix for 0500:D20200
2153 if (er->caid == 0x500 && er->prid == 0xD20200)
2154 er->prid = 0x030600;
2155
2156 //betacrypt ecm with nagra header
2157 if (er->caid == 0x1702 && er->l == 0x89 && er->ecm[3] == 0x07 && er->ecm[4] == 0x84)
2158 er->caid = 0x1833;
2159
2160 /* END quickfixes */
2161
2162 if (!er->prid)
2163 er->prid = chk_provid(er->ecm, er->caid);
2164
2165 // Set providerid for newcamd clients if none is given
2166 if( (!er->prid) && client->ncd_server ) {
2167 int pi = client->port_idx;
2168 if( pi >= 0 && cfg->ncd_ptab.nports && cfg->ncd_ptab.nports >= pi )
2169 er->prid = cfg->ncd_ptab.ports[pi].ftab.filts[0].prids[0];
2170 }
2171
2172 // CAID not supported or found
2173 if (!er->caid) {
2174 er->rc = 8;
2175 er->rcEx = E2_CAID;
2176 snprintf( er->msglog, MSGLOGSIZE, "CAID not supported or found" );
2177 }
2178
2179 // user expired
2180 if(client->expirationdate && client->expirationdate < client->lastecm)
2181 er->rc = 11;
2182
2183 // out of timeframe
2184 if(client->allowedtimeframe[0] && client->allowedtimeframe[1]) {
2185 struct tm *acttm;
2186 acttm = localtime(&now);
2187 int curtime = (acttm->tm_hour * 60) + acttm->tm_min;
2188 int mintime = client->allowedtimeframe[0];
2189 int maxtime = client->allowedtimeframe[1];
2190 if(!((mintime <= maxtime && curtime > mintime && curtime < maxtime) || (mintime > maxtime && (curtime > mintime || curtime < maxtime)))) {
2191 er->rc = 11;
2192 }
2193 cs_debug("Check Timeframe - result: %d, start: %d, current: %d, end: %d\n",er->rc, mintime, curtime, maxtime);
2194 }
2195
2196 // user disabled
2197 if(client->disabled != 0) {
2198 if (client->failban & BAN_DISABLED){
2199 cs_add_violation(client->ip);
2200 cs_exit(SIGQUIT); // don't know whether this is best way to kill the thread
2201 }
2202 er->rc = 12;
2203 }
2204
2205
2206 // rc<100 -> ecm error
2207 if (er->rc > 99) {
2208
2209 m = er->caid;
2210 er->ocaid = er->caid;
2211 i = er->srvid;
2212
2213 if ((i != client->last_srvid) || (!client->lastswitch)) {
2214 if(cfg->usrfileflag)
2215 cs_statistics(client);
2216 client->lastswitch = now;
2217 }
2218
2219 // user sleeping
2220 if ((client->tosleep) && (now - client->lastswitch > client->tosleep)) {
2221
2222 if (client->failban & BAN_SLEEPING) {
2223 cs_add_violation(client->ip);
2224 cs_exit(SIGQUIT); // todo don't know whether this is best way to kill the thread
2225 }
2226
2227 if (client->c35_sleepsend != 0) {
2228 er->rc = 13; // send stop command CMD08 {00 xx}
2229 } else {
2230 er->rc = 6;
2231 }
2232 }
2233
2234 client->last_srvid = i;
2235 client->last_caid = m;
2236
2237 for (j = 0; (j < 6) && (er->rc > 99); j++)
2238 {
2239 switch(j) {
2240
2241 case 0:
2242 // fake (uniq)
2243 if (client->dup)
2244 er->rc = 7;
2245 break;
2246
2247 case 1:
2248 // invalid (caid)
2249 if (!chk_bcaid(er, &client->ctab)) {
2250 er->rc = 8;
2251 er->rcEx = E2_CAID;
2252 snprintf( er->msglog, MSGLOGSIZE, "invalid caid %x",er->caid );
2253 }
2254 break;
2255
2256 case 2:
2257 // invalid (srvid)
2258 if (!chk_srvid(client, er))
2259 {
2260 er->rc = 8;
2261 snprintf( er->msglog, MSGLOGSIZE, "invalid SID" );
2262 }
2263
2264 break;
2265
2266 case 3:
2267 // invalid (ufilters)
2268 if (!chk_ufilters(er))
2269 er->rc = 8;
2270 break;
2271
2272 case 4:
2273 // invalid (sfilter)
2274 if (!chk_sfilter(er, ph[client->ctyp].ptab))
2275 er->rc = 8;
2276 break;
2277
2278 case 5:
2279 // corrupt
2280 if( (i = er->l - (er->ecm[2] + 3)) ) {
2281 if (i > 0) {
2282 cs_debug("warning: ecm size adjusted from 0x%X to 0x%X",
2283 er->l, er->ecm[2] + 3);
2284 er->l = (er->ecm[2] + 3);
2285 }
2286 else
2287 er->rc = 9;
2288 }
2289 break;
2290 }
2291 }
2292 }
2293
2294 //Schlocke: above checks could change er->rc so
2295 if (er->rc > 99) {
2296 /*BetaCrypt tunneling
2297 *moved behind the check routines,
2298 *because newcamd ECM will fail
2299 *if ECM is converted before
2300 */
2301 if (&client->ttab)
2302 cs_betatunnel(er);
2303
2304 // ignore ecm ...
2305 int offset = 3;
2306 // ... and betacrypt header for cache md5 calculation
2307 if ((er->caid >> 8) == 0x17)
2308 offset = 13;
2309
2310 // store ECM in cache
2311 memcpy(er->ecmd5, MD5(er->ecm+offset, er->l-offset, client->dump), CS_ECMSTORESIZE);
2312
2313 // cache1
2314 if (check_cwcache1(er, client->grp))
2315 er->rc = 1;
2316 else if (check_and_store_ecmcache(er, client->grp))
2317 return;
2318
2319#ifdef CS_ANTICASC
2320 ac_chk(er, 0);
2321#endif
2322 }
2323
2324 if(er->rc > 99) {
2325 er->reader_avail=0;
2326 struct s_reader *rdr;
2327 for (i=0,rdr=first_reader; rdr ; rdr=rdr->next, i++)
2328 if (matching_reader(er, rdr)) {
2329 er->matching_rdr[i] = (rdr->fallback)? 2: 1;
2330 if (cfg->lb_mode || !rdr->fallback)
2331 er->reader_avail++;
2332 }
2333
2334 if (cfg->lb_mode) {
2335 cs_debug_mask(D_TRACE, "requesting client %s best reader for %04X/%06X/%04X",
2336 username(client), er->caid, er->prid, er->srvid);
2337 get_best_reader(er);
2338 }
2339
2340 m = update_reader_count(er);
2341
2342 switch(m) {
2343 // no reader -> not found
2344 case 0:
2345 er->rc = 4;
2346 if (!er->rcEx)
2347 er->rcEx = E2_GROUP;
2348 break;
2349
2350 // fallbacks only, switch them
2351 case 2:
2352 for (i=0,rdr=first_reader; rdr ; rdr=rdr->next, i++)
2353 er->matching_rdr[i]>>=1;
2354 }
2355 }
2356
2357 if (er->rc < 100) {
2358 if (cfg->delay)
2359 cs_sleepms(cfg->delay);
2360
2361 send_dcw(client, er);
2362 return;
2363 }
2364
2365 er->rcEx = 0;
2366 request_cw(er, 0, cfg->preferlocalcards ? 1 : 0);
2367}
2368
2369void log_emm_request(struct s_reader *rdr)
2370{
2371 cs_log("%s emm-request sent (reader=%s, caid=%04X, auprovid=%06lX)",
2372 username(cur_client()), rdr->label, rdr->caid[0],
2373 rdr->auprovid ? rdr->auprovid : b2i(4, rdr->prid[0]));
2374}
2375
2376void do_emm(struct s_client * client, EMM_PACKET *ep)
2377{
2378 char *typtext[]={"unknown", "unique", "shared", "global"};
2379
2380 struct s_reader *aureader = client->aureader;
2381 cs_ddump_mask(D_EMM, ep->emm, ep->l, "emm:");
2382
2383 //Unique Id matching for pay-per-view channels:
2384 if (client->autoau) {
2385 struct s_reader *rdr;
2386 for (rdr=first_reader; rdr ; rdr=rdr->next)
2387 if (rdr->card_system>0 && !rdr->audisabled)
2388 if (reader_get_emm_type(ep, rdr)) //decodes ep->type and ep->hexserial from the EMM
2389 if (memcmp(ep->hexserial, rdr->hexserial, sizeof(ep->hexserial))==0) {
2390 aureader = rdr;
2391 break; //
2392 }
2393 }
2394
2395 if (!aureader) {
2396 cs_debug_mask(D_EMM, "emm disabled, client has no au-reader!");
2397 return;
2398 }
2399
2400 //2nd check for audisabled.
2401 if (aureader->audisabled) {
2402 cs_debug_mask(D_EMM, "AU is disabled for reader %s", aureader->label);
2403 return;
2404 }
2405
2406 if (aureader->card_system>0) {
2407 if (!reader_get_emm_type(ep, aureader)) { //decodes ep->type and ep->hexserial from the EMM
2408 cs_debug_mask(D_EMM, "emm skipped");
2409 return;
2410 }
2411 }
2412 else {
2413 cs_debug_mask(D_EMM, "emm skipped, reader %s has no cardsystem defined!", aureader->label);
2414 return;
2415 }
2416
2417 //test: EMM becomes skipped if auprivid doesn't match with provid from EMM
2418 if(aureader->auprovid && b2i(4, ep->provid)) {
2419 if(aureader->auprovid != b2i(4, ep->provid)) {
2420 cs_debug_mask(D_EMM, "emm skipped, reader %s auprovid doesn't match %06lX != %06lX!", aureader->label, aureader->auprovid, b2i(4, ep->provid));
2421 return;
2422 }
2423 }
2424
2425 cs_debug_mask(D_EMM, "emmtype %s. Reader %s has serial %s.", typtext[ep->type], aureader->label, cs_hexdump(0, aureader->hexserial, 8));
2426 cs_ddump_mask(D_EMM, ep->hexserial, 8, "emm UA/SA:");
2427
2428 client->last=time((time_t)0);
2429 if (aureader->b_nano[ep->emm[0]] & 0x02) //should this nano be saved?
2430 {
2431 char token[256];
2432 FILE *fp;
2433 time_t rawtime;
2434 time (&rawtime);
2435 struct tm *timeinfo;
2436 timeinfo = localtime (&rawtime); /* to access LOCAL date/time info */
2437 char buf[80];
2438 strftime (buf, 80, "%Y/%m/%d %H:%M:%S", timeinfo);
2439 sprintf (token, "%s%s_emm.log", cs_confdir, aureader->label);
2440 int emm_length = ((ep->emm[1] & 0x0f) << 8) | ep->emm[2];
2441
2442 if (!(fp = fopen (token, "a")))
2443 {
2444 cs_log ("ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
2445 }
2446 else
2447 {
2448 fprintf (fp, "%s %s ", buf, cs_hexdump(0, ep->hexserial, 8));
2449 fprintf (fp, "%s\n", cs_hexdump(0, ep->emm, emm_length + 3));
2450 fclose (fp);
2451 cs_log ("Succesfully added EMM to %s.", token);
2452 }
2453
2454 sprintf (token, "%s%s_emm.bin", cs_confdir, aureader->label);
2455 if (!(fp = fopen (token, "ab")))
2456 {
2457 cs_log ("ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
2458 }
2459 else
2460 {
2461 if ((int)fwrite(ep->emm, 1, emm_length+3, fp) == emm_length+3)
2462 {
2463 cs_log ("Succesfully added binary EMM to %s.", token);
2464 }
2465 else
2466 {
2467 cs_log ("ERROR: Cannot write binary EMM to %s (errno=%d: %s)\n", token, errno, strerror(errno));
2468 }
2469 fclose (fp);
2470 }
2471 }
2472
2473 int is_blocked = 0;
2474 switch (ep->type) {
2475 case UNKNOWN: is_blocked = aureader->blockemm_unknown;
2476 break;
2477 case UNIQUE: is_blocked = aureader->blockemm_u;
2478 break;
2479 case SHARED: is_blocked = aureader->blockemm_s;
2480 break;
2481 case GLOBAL: is_blocked = aureader->blockemm_g;
2482 break;
2483 }
2484
2485 if (is_blocked != 0) {
2486#ifdef WEBIF
2487 aureader->emmblocked[ep->type]++;
2488 is_blocked = aureader->emmblocked[ep->type];
2489#endif
2490 /* we have to write the log for blocked EMM here because
2491 this EMM never reach the reader module where the rest
2492 of EMM log is done. */
2493 if (aureader->logemm & 0x08) {
2494 cs_log("%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms) by %s",
2495 client->usr,
2496 typtext[ep->type],
2497 ep->emm[2],
2498 is_blocked,
2499 aureader->label);
2500 }
2501 return;
2502 }
2503
2504
2505 client->lastemm = time((time_t)0);
2506
2507 if (aureader->card_system > 0) {
2508 if (!check_emm_cardsystem(aureader, ep)) { // wrong caid
2509 client->emmnok++;
2510 return;
2511 }
2512 client->emmok++;
2513 }
2514 ep->client = cur_client();
2515 cs_debug_mask(D_EMM, "emm is being sent to reader %s.", aureader->label);
2516 write_to_pipe(aureader->fd, PIP_ID_EMM, (uchar *) ep, sizeof(EMM_PACKET));
2517}
2518
2519int comp_timeb(struct timeb *tpa, struct timeb *tpb)
2520{
2521 if (tpa->time>tpb->time) return(1);
2522 if (tpa->time<tpb->time) return(-1);
2523 if (tpa->millitm>tpb->millitm) return(1);
2524 if (tpa->millitm<tpb->millitm) return(-1);
2525 return(0);
2526}
2527
2528struct timeval *chk_pending(struct timeb tp_ctimeout)
2529{
2530 int i;
2531 ulong td;
2532 struct timeb tpn, tpe, tpc; // <n>ow, <e>nd, <c>heck
2533
2534 ECM_REQUEST *er;
2535 cs_ftime(&tpn);
2536 tpe=tp_ctimeout; // latest delay -> disconnect
2537
2538 struct s_client *cl = cur_client();
2539
2540 if (cl->ecmtask)
2541 i=(ph[cl->ctyp].multi)?CS_MAXPENDING:1;
2542 else
2543 i=0;
2544
2545 //cs_log("num pend=%d", i);
2546
2547 for (--i; i>=0; i--) {
2548 if (cl->ecmtask[i].rc>=99) { // check all pending ecm-requests
2549 int act, j;
2550 er=&cl->ecmtask[i];
2551 tpc=er->tps;
2552 unsigned int tt;
2553 tt = (er->stage) ? cfg->ctimeout : cfg->ftimeout;
2554 tpc.time +=tt / 1000;
2555 tpc.millitm += tt % 1000;
2556 if (!er->stage && er->rc>=100) {
2557 struct s_reader *rdr;
2558 for (j=0, act=1, rdr=first_reader; (act) && rdr ; rdr=rdr->next, j++) {
2559 if (cfg->preferlocalcards && !er->locals_done) {
2560 if ((er->matching_rdr[j]&1) && !(rdr->typ & R_IS_NETWORK))
2561 act=0;
2562 } else if (cfg->preferlocalcards && er->locals_done) {
2563 if ((er->matching_rdr[j]&1) && (rdr->typ & R_IS_NETWORK))
2564 act=0;
2565 } else {
2566 if (er->matching_rdr[j]&1)
2567 act=0;
2568 }
2569 }
2570
2571 //cs_log("stage 0, act=%d r0=%d, r1=%d, r2=%d, r3=%d, r4=%d r5=%d", act,
2572 // er->matching_rdr[0], er->matching_rdr[1], er->matching_rdr[2],
2573 // er->matching_rdr[3], er->matching_rdr[4], er->matching_rdr[5]);
2574
2575 if (act) {
2576 int inc_stage = 1;
2577 if (cfg->preferlocalcards && !er->locals_done) {
2578 er->locals_done = 1;
2579 struct s_reader *rdr;
2580 for (rdr=first_reader; rdr ; rdr=rdr->next)
2581 if (rdr->typ & R_IS_NETWORK)
2582 inc_stage = 0;
2583 }
2584 unsigned int tt;
2585 if (!inc_stage) {
2586 request_cw(er, er->stage, 2);
2587 tt = 1000 * (tpn.time - er->tps.time) + tpn.millitm - er->tps.millitm;
2588 tpc.time += tt / 1000;
2589 tpc.millitm += tt % 1000;
2590 } else {
2591 er->locals_done = 0;
2592 er->stage++;
2593 request_cw(er, er->stage, cfg->preferlocalcards ? 1 : 0);
2594
2595 tt = (cfg->ctimeout-cfg->ftimeout);
2596 tpc.time += tt / 1000;
2597 tpc.millitm += tt % 1000;
2598 }
2599 }
2600 }
2601 if (comp_timeb(&tpn, &tpc)>0) { // action needed
2602 //cs_log("Action now %d.%03d", tpn.time, tpn.millitm);
2603 //cs_log(" %d.%03d", tpc.time, tpc.millitm);
2604 if (er->stage) {
2605 er->rc=5; // timeout
2606 if (cfg->lb_mode) {
2607 int r;
2608 struct s_reader *rdr;
2609 for (r=0,rdr=first_reader; rdr ; rdr=rdr->next, r++)
2610 if (er->matching_rdr[r])
2611 send_reader_stat(rdr, er, 5);
2612 }
2613 send_dcw(cl, er);
2614 continue;
2615 } else {
2616 er->stage++;
2617 if (er->rc>=100) //do not request rc=99
2618 request_cw(er, er->stage, 0);
2619 unsigned int tt;
2620 tt = (cfg->ctimeout-cfg->ftimeout);
2621 tpc.time += tt / 1000;
2622 tpc.millitm += tt % 1000;
2623 }
2624 }
2625 //build_delay(&tpe, &tpc);
2626 if (comp_timeb(&tpe, &tpc)>0) {
2627 tpe.time=tpc.time;
2628 tpe.millitm=tpc.millitm;
2629 }
2630 }
2631 }
2632
2633 td=(tpe.time-tpn.time)*1000+(tpe.millitm-tpn.millitm)+5;
2634 cl->tv.tv_sec = td/1000;
2635 cl->tv.tv_usec = (td%1000)*1000;
2636 //cs_log("delay %d.%06d", tv.tv_sec, tv.tv_usec);
2637 return(&cl->tv);
2638}
2639
2640int process_input(uchar *buf, int l, int timeout)
2641{
2642 int rc;
2643 fd_set fds;
2644 struct timeb tp;
2645
2646 struct s_client *cl = cur_client();
2647
2648 cs_ftime(&tp);
2649 tp.time+=timeout;
2650
2651 while (1) {
2652 FD_ZERO(&fds);
2653
2654 if (cl->pfd)
2655 FD_SET(cl->pfd, &fds);
2656
2657 FD_SET(cl->fd_m2c_c, &fds);
2658
2659 rc=select(((cl->pfd > cl->fd_m2c_c) ? cl->pfd : cl->fd_m2c_c)+1, &fds, 0, 0, chk_pending(tp));
2660 if (rc<0) {
2661 if (errno==EINTR) continue;
2662 else return(0);
2663 }
2664
2665 if (FD_ISSET(cl->fd_m2c_c, &fds)) { // read from pipe
2666 if (process_client_pipe(cl, buf, l)==PIP_ID_UDP) {
2667 rc=ph[cl->ctyp].recv(cl, buf, l);
2668 break;
2669 }
2670 }
2671
2672 if (cl->pfd && FD_ISSET(cl->pfd, &fds)) { // read from client
2673 rc=ph[cl->ctyp].recv(cl, buf, l);
2674 break;
2675 }
2676
2677 if (tp.time<=time((time_t *)0)) { // client maxidle reached
2678 rc=(-9);
2679 break;
2680 }
2681 }
2682 return(rc);
2683}
2684
2685static void restart_clients()
2686{
2687 cs_log("restarting clients");
2688 struct s_client *cl;
2689 for (cl=first_client->next; cl ; cl=cl->next)
2690 if (cl->typ=='c' && ph[cl->ctyp].type & MOD_CONN_NET) {
2691 kill_thread(cl);
2692 cs_log("killing client c %8X", (unsigned long)(cl->thread));
2693 }
2694}
2695
2696
2697static void process_master_pipe(int mfdr)
2698{
2699 int n;
2700 uchar *ptr;
2701
2702 switch(n=read_from_pipe(mfdr, &ptr, 1))
2703 {
2704 case PIP_ID_KCL: //Kill all clients
2705 restart_clients();
2706 break;
2707 case PIP_ID_ERR:
2708 cs_exit(1); //better than reading from dead pipe!
2709 break;
2710 default:
2711 cs_log("unhandled pipe message %d (master pipe)", n);
2712 break;
2713 }
2714 if (ptr) free(ptr);
2715}
2716
2717
2718int process_client_pipe(struct s_client *cl, uchar *buf, int l) {
2719 uchar *ptr;
2720 unsigned short n;
2721 int pipeCmd = read_from_pipe(cl->fd_m2c_c, &ptr, 0);
2722
2723 switch(pipeCmd) {
2724 case PIP_ID_ECM:
2725 chk_dcw(cl, (ECM_REQUEST *)ptr);
2726 break;
2727 case PIP_ID_UDP:
2728 if (ptr[0]!='U') {
2729 cs_log("INTERNAL PIPE-ERROR");
2730 }
2731 memcpy(&n, ptr+1, 2);
2732 if (n+3<=l) {
2733 memcpy(buf, ptr, n+3);
2734 }
2735 break;
2736 case PIP_ID_ERR:
2737 cs_exit(1);
2738 break;
2739 default:
2740 cs_log("unhandled pipe message %d (client %s)", pipeCmd, cl->usr);
2741 break;
2742 }
2743 if (ptr) free(ptr);
2744 return pipeCmd;
2745}
2746
2747void cs_log_config()
2748{
2749 uchar buf[20];
2750
2751 if (cfg->nice!=99)
2752 sprintf((char *)buf, ", nice=%d", cfg->nice);
2753 else
2754 buf[0]='\0';
2755 cs_log("version=%s, build #%s, system=%s-%s-%s%s", CS_VERSION_X, CS_SVN_VERSION, CS_OS_CPU, CS_OS_HW, CS_OS_SYS, buf);
2756 cs_log("client max. idle=%d sec, debug level=%d", cfg->cmaxidle, cs_dblevel);
2757
2758 if( cfg->max_log_size )
2759 sprintf((char *)buf, "%d Kb", cfg->max_log_size);
2760 else
2761 strcpy((char *)buf, "unlimited");
2762 cs_log("max. logsize=%s", buf);
2763 cs_log("client timeout=%lu ms, fallback timeout=%lu ms, cache delay=%d ms",
2764 cfg->ctimeout, cfg->ftimeout, cfg->delay);
2765}
2766
2767void cs_waitforcardinit()
2768{
2769 if (cfg->waitforcards)
2770 {
2771 cs_log("waiting for local card init");
2772 int card_init_done;
2773 cs_sleepms(3000); // short sleep for card detect to work proberly
2774 do {
2775 card_init_done = 1;
2776 struct s_reader *rdr;
2777 for (rdr=first_reader; rdr ; rdr=rdr->next)
2778 if (!(rdr->typ & R_IS_CASCADING) && rdr->card_status == CARD_NEED_INIT) {
2779 card_init_done = 0;
2780 break;
2781 }
2782 cs_sleepms(300); // wait a little bit
2783 //alarm(cfg->cmaxidle + cfg->ctimeout / 1000 + 1);
2784 } while (!card_init_done);
2785 cs_log("init for all local cards done");
2786 }
2787}
2788
2789int accept_connection(int i, int j) {
2790 struct sockaddr_in cad;
2791 int scad,n;
2792 scad = sizeof(cad);
2793 uchar buf[2048];
2794
2795 if (ph[i].type==MOD_CONN_UDP) {
2796
2797 if ((n=recvfrom(ph[i].ptab->ports[j].fd, buf+3, sizeof(buf)-3, 0, (struct sockaddr *)&cad, (socklen_t *)&scad))>0) {
2798 struct s_client *cl;
2799 cl=idx_from_ip(cs_inet_order(cad.sin_addr.s_addr), ntohs(cad.sin_port));
2800
2801 unsigned short rl;
2802 rl=n;
2803 buf[0]='U';
2804 memcpy(buf+1, &rl, 2);
2805
2806 if (!cl) {
2807 if (cs_check_violation((uint)cs_inet_order(cad.sin_addr.s_addr)))
2808 return 0;
2809 //printf("IP: %s - %d\n", inet_ntoa(*(struct in_addr *)&cad.sin_addr.s_addr), cad.sin_addr.s_addr);
2810
2811 cl = cs_fork(cs_inet_order(cad.sin_addr.s_addr));
2812 if (!cl) return 0;
2813
2814 cl->ctyp=i;
2815 cl->port_idx=j;
2816 cl->udp_fd=ph[i].ptab->ports[j].fd;
2817 cl->udp_sa=cad;
2818
2819 cl->port=ntohs(cad.sin_port);
2820 cl->typ='c';
2821
2822 write_to_pipe(cl->fd_m2c, PIP_ID_UDP, (uchar*)&buf, n+3);
2823
2824 pthread_attr_t attr;
2825 pthread_attr_init(&attr);
2826#ifndef TUXBOX
2827 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
2828#endif
2829 pthread_create(&cl->thread, &attr, ph[i].s_handler, (void *) cl);
2830 pthread_detach(cl->thread);
2831 pthread_attr_destroy(&attr);
2832 } else {
2833 write_to_pipe(cl->fd_m2c, PIP_ID_UDP, (uchar*)&buf, n+3);
2834 }
2835 }
2836 } else { //TCP
2837
2838 int pfd3;
2839 if ((pfd3=accept(ph[i].ptab->ports[j].fd, (struct sockaddr *)&cad, (socklen_t *)&scad))>0) {
2840
2841 if (cs_check_violation((uint)cs_inet_order(cad.sin_addr.s_addr))) {
2842 close(pfd3);
2843 return 0;
2844 }
2845
2846 struct s_client * cl = cs_fork(cs_inet_order(cad.sin_addr.s_addr));
2847 if (cl == NULL) {
2848 close(pfd3);
2849 return 0;
2850 }
2851
2852 cl->ctyp=i;
2853 cl->udp_fd=pfd3;
2854 cl->port_idx=j;
2855
2856 cl->pfd=pfd3;
2857 cl->port=ntohs(cad.sin_port);
2858 cl->typ='c';
2859
2860 pthread_attr_t attr;
2861 pthread_attr_init(&attr);
2862#ifndef TUXBOX
2863 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
2864#endif
2865 pthread_create(&cl->thread, &attr, ph[i].s_handler, (void*) cl);
2866 pthread_detach(cl->thread);
2867 pthread_attr_destroy(&attr);
2868 }
2869 }
2870 return 0;
2871}
2872
2873/**
2874 * get tmp dir
2875 **/
2876char * get_tmp_dir()
2877{
2878 if (cs_tmpdir[0])
2879 return cs_tmpdir;
2880
2881#ifdef OS_CYGWIN32
2882 char *d = getenv("TMPDIR");
2883 if (!d || !d[0])
2884 d = getenv("TMP");
2885 if (!d || !d[0])
2886 d = getenv("TEMP");
2887 if (!d || !d[0])
2888 getcwd(cs_tmpdir, sizeof(cs_tmpdir)-1);
2889
2890 strcpy(cs_tmpdir, d);
2891 char *p = cs_tmpdir;
2892 while(*p) p++;
2893 p--;
2894 if (*p != '/' && *p != '\\')
2895 strcat(cs_tmpdir, "/");
2896 strcat(cs_tmpdir, "_oscam");
2897#else
2898 strcpy(cs_tmpdir, "/tmp/.oscam");
2899#endif
2900 mkdir(cs_tmpdir, S_IRWXU);
2901 return cs_tmpdir;
2902}
2903
2904
2905int main (int argc, char *argv[])
2906{
2907
2908
2909if (pthread_key_create(&getclient, NULL)) {
2910 fprintf(stderr, "Could not create getclient, exiting...");
2911 exit(1);
2912}
2913
2914#ifdef CS_LED
2915 cs_switch_led(LED1A, LED_DEFAULT);
2916 cs_switch_led(LED1A, LED_ON);
2917#endif
2918
2919 //struct sockaddr_in cad; /* structure to hold client's address */
2920 //int scad; /* length of address */
2921 //int fd; /* socket descriptors */
2922 int i, j;
2923 int bg=0;
2924 int gfd; //nph,
2925 int fdp[2];
2926 int mfdr=0; // Master FD (read)
2927 int fd_c2m=0;
2928
2929 cfg = malloc(sizeof(struct s_config));
2930 memset(cfg, 0, sizeof(struct s_config));
2931
2932 void (*mod_def[])(struct s_module *)=
2933 {
2934#ifdef MODULE_MONITOR
2935 module_monitor,
2936#endif
2937#ifdef MODULE_CAMD33
2938 module_camd33,
2939#endif
2940#ifdef MODULE_CAMD35
2941 module_camd35,
2942#endif
2943#ifdef MODULE_CAMD35_TCP
2944 module_camd35_tcp,
2945#endif
2946#ifdef MODULE_NEWCAMD
2947 module_newcamd,
2948#endif
2949#ifdef MODULE_CCCAM
2950 module_cccam,
2951#endif
2952#ifdef MODULE_CONSTCW
2953 module_constcw,
2954#endif
2955#ifdef CS_WITH_GBOX
2956 module_gbox,
2957#endif
2958#ifdef MODULE_RADEGAST
2959 module_radegast,
2960#endif
2961#ifdef MODULE_SERIAL
2962 module_oscam_ser,
2963#endif
2964#ifdef HAVE_DVBAPI
2965 module_dvbapi,
2966#endif
2967 0
2968 };
2969
2970 void (*cardsystem_def[])(struct s_cardsystem *)=
2971 {
2972#ifdef READER_NAGRA
2973 reader_nagra,
2974#endif
2975#ifdef READER_IRDETO
2976 reader_irdeto,
2977#endif
2978#ifdef READER_CONAX
2979 reader_conax,
2980#endif
2981#ifdef READER_CRYPTOWORKS
2982 reader_cryptoworks,
2983#endif
2984#ifdef READER_SECA
2985 reader_seca,
2986#endif
2987#ifdef READER_VIACCESS
2988 reader_viaccess,
2989#endif
2990#ifdef READER_VIDEOGUARD
2991 reader_videoguard1,
2992 reader_videoguard2,
2993 reader_videoguard12,
2994#endif
2995#ifdef READER_DRE
2996 reader_dre,
2997#endif
2998#ifdef READER_TONGFANG
2999 reader_tongfang,
3000#endif
3001 0
3002 };
3003
3004 while ((i=getopt(argc, argv, "bc:t:d:hm:"))!=EOF)
3005 {
3006 switch(i) {
3007 case 'b':
3008 bg=1;
3009 break;
3010 case 'c':
3011 cs_strncpy(cs_confdir, optarg, sizeof(cs_confdir));
3012 break;
3013 case 'd':
3014 cs_dblevel=atoi(optarg);
3015 break;
3016 case 't':
3017 mkdir(optarg, S_IRWXU);
3018 j = open(optarg, O_RDONLY);
3019 if (j >= 0) {
3020 close(j);
3021 cs_strncpy(cs_tmpdir, optarg, sizeof(cs_tmpdir));
3022 } else {
3023 printf("WARNING: tmpdir does not exist. using default value.\n");
3024 }
3025 break;
3026 case 'm':
3027 printf("WARNING: -m parameter is deprecated, ignoring it.\n");
3028 break;
3029 case 'h':
3030 default :
3031 usage();
3032 }
3033 }
3034 if (cs_confdir[strlen(cs_confdir)]!='/') strcat(cs_confdir, "/");
3035 init_shm();
3036 init_config();
3037 init_stat();
3038 cfg->debuglvl = cs_dblevel; // give static debuglevel to outer world
3039 for (i=0; mod_def[i]; i++) // must be later BEFORE init_config()
3040 {
3041 memset(&ph[i], 0, sizeof(struct s_module));
3042 mod_def[i](&ph[i]);
3043 }
3044 for (i=0; cardsystem_def[i]; i++) // must be later BEFORE init_config()
3045 {
3046 memset(&cardsystem[i], 0, sizeof(struct s_cardsystem));
3047 cardsystem_def[i](&cardsystem[i]);
3048 }
3049
3050
3051 cs_log("auth size=%d", sizeof(struct s_auth));
3052
3053 init_rnd();
3054 init_sidtab();
3055 init_readerdb();
3056 init_userdb(&cfg->account);
3057 init_signal();
3058 init_srvid();
3059 init_tierid();
3060 //Todo #ifdef CCCAM
3061 init_provid();
3062
3063 init_len4caid();
3064#ifdef IRDETO_GUESSING
3065 init_irdeto_guess_tab();
3066#endif
3067
3068
3069 if (pipe(fdp))
3070 {
3071 cs_log("Cannot create pipe (errno=%d: %s)", errno, strerror(errno));
3072 cs_exit(1);
3073 }
3074 mfdr=fdp[0];
3075 fd_c2m=fdp[1];
3076 gfd=mfdr+1;
3077
3078 first_client->fd_m2c=fd_c2m;
3079 first_client->fd_m2c_c=mfdr;
3080
3081#ifdef OS_MACOSX
3082 if (bg && daemon_compat(1,0))
3083#else
3084 if (bg && daemon(1,0))
3085#endif
3086 {
3087 cs_log("Error starting in background (errno=%d: %s)", errno, strerror(errno));
3088 cs_exit(1);
3089 }
3090
3091 write_versionfile();
3092 server_pid = getpid();
3093
3094#ifdef AZBOX
3095 openxcas_debug_message_onoff(1); // debug
3096
3097 if (openxcas_open_with_smartcard("oscamCAS") < 0) {
3098 cs_log("openxcas: could not init");
3099 }
3100#endif
3101
3102 for (i=0; i<CS_MAX_MOD; i++)
3103 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
3104 for(j=0; j<ph[i].ptab->nports; j++)
3105 {
3106 start_listener(&ph[i], j);
3107 if( ph[i].ptab->ports[j].fd+1>gfd )
3108 gfd=ph[i].ptab->ports[j].fd+1;
3109 }
3110
3111 //set time for server to now to avoid 0 in monitor/webif
3112 first_client->last=time((time_t *)0);
3113
3114#ifdef WEBIF
3115 if(cfg->http_port == 0)
3116 cs_log("http disabled");
3117 else
3118 start_thread((void *) &http_srv, "http");
3119#endif
3120
3121 init_cardreader();
3122
3123 cs_waitforcardinit();
3124
3125#ifdef CS_LED
3126 cs_switch_led(LED1A, LED_OFF);
3127 cs_switch_led(LED1B, LED_ON);
3128#endif
3129
3130#ifdef QBOXHD_LED
3131 if(!cfg->disableqboxhdled)
3132 cs_log("QboxHD LED enabled");
3133 qboxhd_led_blink(QBOXHD_LED_COLOR_YELLOW,QBOXHD_LED_BLINK_FAST);
3134 qboxhd_led_blink(QBOXHD_LED_COLOR_RED,QBOXHD_LED_BLINK_FAST);
3135 qboxhd_led_blink(QBOXHD_LED_COLOR_GREEN,QBOXHD_LED_BLINK_FAST);
3136 qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE,QBOXHD_LED_BLINK_FAST);
3137 qboxhd_led_blink(QBOXHD_LED_COLOR_MAGENTA,QBOXHD_LED_BLINK_FAST);
3138#endif
3139
3140#ifdef CS_ANTICASC
3141 if( !cfg->ac_enabled )
3142 cs_log("anti cascading disabled");
3143 else {
3144 init_ac();
3145 start_thread((void *) &start_anticascader, "anticascader"); // 96
3146
3147 }
3148#endif
3149
3150 for (i=0; i<CS_MAX_MOD; i++)
3151 if (ph[i].type & MOD_CONN_SERIAL) // for now: oscam_ser only
3152 if (ph[i].s_handler)
3153 ph[i].s_handler(i);
3154
3155 //cs_close_log();
3156 while (1) {
3157 fd_set fds;
3158
3159 do {
3160 FD_ZERO(&fds);
3161 FD_SET(mfdr, &fds);
3162 for (i=0; i<CS_MAX_MOD; i++)
3163 if ( (ph[i].type & MOD_CONN_NET) && ph[i].ptab )
3164 for (j=0; j<ph[i].ptab->nports; j++)
3165 if (ph[i].ptab->ports[j].fd)
3166 FD_SET(ph[i].ptab->ports[j].fd, &fds);
3167 errno=0;
3168 select(gfd, &fds, 0, 0, 0);
3169 } while (errno==EINTR);
3170
3171 first_client->last=time((time_t *)0);
3172
3173 if (FD_ISSET(mfdr, &fds)) {
3174 process_master_pipe(mfdr);
3175 }
3176 for (i=0; i<CS_MAX_MOD; i++) {
3177 if( (ph[i].type & MOD_CONN_NET) && ph[i].ptab ) {
3178 for( j=0; j<ph[i].ptab->nports; j++ ) {
3179 if( ph[i].ptab->ports[j].fd && FD_ISSET(ph[i].ptab->ports[j].fd, &fds) ) {
3180 accept_connection(i,j);
3181 }
3182 }
3183 } // if (ph[i].type & MOD_CONN_NET)
3184 }
3185 }
3186
3187#ifdef AZBOX
3188 if (openxcas_close() < 0) {
3189 cs_log("openxcas: could not close");
3190 }
3191#endif
3192
3193 cs_exit(1);
3194}
3195
3196#ifdef CS_LED
3197void cs_switch_led(int led, int action) {
3198
3199 if(action < 2) { // only LED_ON and LED_OFF
3200 char ledfile[256];
3201 FILE *f;
3202
3203 #ifdef DOCKSTAR
3204 switch(led){
3205 case LED1A:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
3206 break;
3207 case LED1B:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
3208 break;
3209 case LED2:snprintf(ledfile, 255, "/sys/class/leds/dockstar:green:health/brightness");
3210 break;
3211 case LED3:snprintf(ledfile, 255, "/sys/class/leds/dockstar:orange:misc/brightness");
3212 break;
3213 }
3214 #else
3215 switch(led){
3216 case LED1A:snprintf(ledfile, 255, "/sys/class/leds/nslu2:red:status/brightness");
3217 break;
3218 case LED1B:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:ready/brightness");
3219 break;
3220 case LED2:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-1/brightness");
3221 break;
3222 case LED3:snprintf(ledfile, 255, "/sys/class/leds/nslu2:green:disk-2/brightness");
3223 break;
3224 }
3225 #endif
3226
3227 if (!(f=fopen(ledfile, "w"))){
3228 // FIXME: sometimes cs_log was not available when calling cs_switch_led -> signal 11
3229 //cs_log("Cannot open file \"%s\" (errno=%d)", ledfile, errno);
3230 return;
3231 }
3232 fprintf(f,"%d", action);
3233 fclose(f);
3234 } else { // LED Macros
3235 switch(action){
3236 case LED_DEFAULT:
3237 cs_switch_led(LED1A, LED_OFF);
3238 cs_switch_led(LED1B, LED_OFF);
3239 cs_switch_led(LED2, LED_ON);
3240 cs_switch_led(LED3, LED_OFF);
3241 break;
3242 case LED_BLINK_OFF:
3243 cs_switch_led(led, LED_OFF);
3244 cs_sleepms(100);
3245 cs_switch_led(led, LED_ON);
3246 break;
3247 case LED_BLINK_ON:
3248 cs_switch_led(led, LED_ON);
3249 cs_sleepms(300);
3250 cs_switch_led(led, LED_OFF);
3251 break;
3252 }
3253 }
3254}
3255#endif
3256
3257#ifdef QBOXHD_LED
3258void qboxhd_led_blink(int color, int duration) {
3259 int f;
3260
3261 if (cfg->disableqboxhdled) {
3262 return;
3263 }
3264
3265 // try QboxHD-MINI first
3266 if ( (f = open ( QBOXHDMINI_LED_DEVICE, O_RDWR |O_NONBLOCK )) > -1 ) {
3267 qboxhdmini_led_color_struct qbminiled;
3268 ulong qboxhdmini_color = 0x000000;
3269
3270 if (color != QBOXHD_LED_COLOR_OFF) {
3271 switch(color) {
3272 case QBOXHD_LED_COLOR_RED:
3273 qboxhdmini_color = QBOXHDMINI_LED_COLOR_RED;
3274 break;
3275 case QBOXHD_LED_COLOR_GREEN:
3276 qboxhdmini_color = QBOXHDMINI_LED_COLOR_GREEN;
3277 break;
3278 case QBOXHD_LED_COLOR_BLUE:
3279 qboxhdmini_color = QBOXHDMINI_LED_COLOR_BLUE;
3280 break;
3281 case QBOXHD_LED_COLOR_YELLOW:
3282 qboxhdmini_color = QBOXHDMINI_LED_COLOR_YELLOW;
3283 break;
3284 case QBOXHD_LED_COLOR_MAGENTA:
3285 qboxhdmini_color = QBOXHDMINI_LED_COLOR_MAGENTA;
3286 break;
3287 }
3288
3289 // set LED on with color
3290 qbminiled.red = (uchar)((qboxhdmini_color&0xFF0000)>>16); // R
3291 qbminiled.green = (uchar)((qboxhdmini_color&0x00FF00)>>8); // G
3292 qbminiled.blue = (uchar)(qboxhdmini_color&0x0000FF); // B
3293
3294 ioctl(f,QBOXHDMINI_IOSET_RGB,&qbminiled);
3295 cs_sleepms(duration);
3296 }
3297
3298 // set LED off
3299 qbminiled.red = 0;
3300 qbminiled.green = 0;
3301 qbminiled.blue = 0;
3302
3303 ioctl(f,QBOXHDMINI_IOSET_RGB,&qbminiled);
3304 close(f);
3305
3306 } else if ( (f = open ( QBOXHD_LED_DEVICE, O_RDWR |O_NONBLOCK )) > -1 ) {
3307
3308 qboxhd_led_color_struct qbled;
3309
3310 if (color != QBOXHD_LED_COLOR_OFF) {
3311 // set LED on with color
3312 qbled.H = color;
3313 qbled.S = 99;
3314 qbled.V = 99;
3315 ioctl(f,QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
3316 cs_sleepms(duration);
3317 }
3318
3319 // set LED off
3320 qbled.H = 0;
3321 qbled.S = 0;
3322 qbled.V = 0;
3323 ioctl(f,QBOXHD_SET_LED_ALL_PANEL_COLOR, &qbled);
3324 close(f);
3325 }
3326
3327 return;
3328}
3329#endif
Note: See TracBrowser for help on using the repository browser.