source: trunk/oscam.c@ 4010

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

fix wrong timeout message for distributed ecmtask

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