source: trunk/oscam.c@ 4006

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

add mutex lock for cwcache and add more debug messages for cache problem

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