source: trunk/oscam.c@ 4014

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

next try fixing wrong timeout with betatunnel

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